배경 씬 로더 기능 개선: - BackgroundSceneDatabase 에셋 추가 - 플레이 모드 언로드 시 MarkSceneDirty 오류 수정 - Directional Light 및 NiloToonOverrider 백업/복원 기능 - 빌드 세팅 자동 추가 기능 배경 폴더 구조 정리: - [초금비]방 → [공용]방 이름 변경 - [공용]루프탑 카페 씬 구조 정리 (Day/Night 씬 통합) - 미사용 배경 삭제: [공용]교실, [공용]농구장 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
275 lines
9.8 KiB
C#
275 lines
9.8 KiB
C#
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace Streamingle.Background.Editor
|
|
{
|
|
/// <summary>
|
|
/// 배경 씬에서 라이팅 세팅을 복사해오는 유틸리티
|
|
/// </summary>
|
|
public static class BackgroundLightingCopier
|
|
{
|
|
/// <summary>
|
|
/// 소스 씬에서 타겟 씬으로 라이팅 세팅 복사
|
|
/// </summary>
|
|
public static void CopyLightingSettings(Scene sourceScene, Scene targetScene)
|
|
{
|
|
if (!sourceScene.isLoaded || !targetScene.isLoaded)
|
|
{
|
|
UnityEngine.Debug.LogWarning("소스 씬 또는 타겟 씬이 로드되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
// 1. Environment 설정 복사 (Skybox, Ambient, Fog 등)
|
|
CopyEnvironmentSettings();
|
|
|
|
// 2. 소스 씬의 라이트들을 타겟 씬으로 복사
|
|
CopyLights(sourceScene, targetScene);
|
|
|
|
// 3. Reflection Probe 복사
|
|
CopyReflectionProbes(sourceScene, targetScene);
|
|
|
|
// 4. Light Probe Group 복사
|
|
CopyLightProbeGroups(sourceScene, targetScene);
|
|
|
|
// 5. Volume (Post Processing) 복사
|
|
CopyVolumes(sourceScene, targetScene);
|
|
|
|
UnityEngine.Debug.Log($"라이팅 세팅 복사 완료: {sourceScene.name} → {targetScene.name}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성 씬에 배경 씬의 라이팅 적용
|
|
/// </summary>
|
|
public static void ApplyLightingFromBackgroundScene(Scene backgroundScene)
|
|
{
|
|
if (!backgroundScene.isLoaded)
|
|
{
|
|
UnityEngine.Debug.LogWarning("배경 씬이 로드되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
// Environment 설정 복사
|
|
CopyEnvironmentSettingsFromScene(backgroundScene);
|
|
|
|
UnityEngine.Debug.Log($"라이팅 세팅 적용됨: {backgroundScene.name}");
|
|
}
|
|
|
|
private static void CopyEnvironmentSettings()
|
|
{
|
|
// RenderSettings는 현재 활성 씬에 적용됨
|
|
// Lighting Window에서 설정하는 것들
|
|
}
|
|
|
|
private static void CopyEnvironmentSettingsFromScene(Scene sourceScene)
|
|
{
|
|
// 소스 씬을 활성 씬으로 설정하여 RenderSettings 가져오기
|
|
var previousActiveScene = SceneManager.GetActiveScene();
|
|
|
|
// 소스 씬에서 Environment 관련 오브젝트 찾기
|
|
var rootObjects = sourceScene.GetRootGameObjects();
|
|
|
|
foreach (var obj in rootObjects)
|
|
{
|
|
// Directional Light (Sun) 찾기
|
|
var lights = obj.GetComponentsInChildren<Light>(true);
|
|
foreach (var light in lights)
|
|
{
|
|
if (light.type == LightType.Directional)
|
|
{
|
|
// Sun Source로 설정
|
|
RenderSettings.sun = light;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Volume 찾기 (Global Volume의 경우 환경 설정 포함)
|
|
var volumes = obj.GetComponentsInChildren<Volume>(true);
|
|
foreach (var volume in volumes)
|
|
{
|
|
if (volume.isGlobal && volume.sharedProfile != null)
|
|
{
|
|
// Global Volume의 프로파일에서 환경 설정 복사 가능
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void CopyLights(Scene sourceScene, Scene targetScene)
|
|
{
|
|
var sourceRoots = sourceScene.GetRootGameObjects();
|
|
var lightsContainer = GetOrCreateLightingContainer(targetScene, "Background Lights");
|
|
|
|
foreach (var root in sourceRoots)
|
|
{
|
|
var lights = root.GetComponentsInChildren<Light>(true);
|
|
foreach (var light in lights)
|
|
{
|
|
// 라이트 복제
|
|
var newLightObj = Object.Instantiate(light.gameObject, lightsContainer.transform);
|
|
newLightObj.name = $"[BG] {light.gameObject.name}";
|
|
|
|
// 씬 이동
|
|
SceneManager.MoveGameObjectToScene(newLightObj, targetScene);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void CopyReflectionProbes(Scene sourceScene, Scene targetScene)
|
|
{
|
|
var sourceRoots = sourceScene.GetRootGameObjects();
|
|
var container = GetOrCreateLightingContainer(targetScene, "Background ReflectionProbes");
|
|
|
|
foreach (var root in sourceRoots)
|
|
{
|
|
var probes = root.GetComponentsInChildren<ReflectionProbe>(true);
|
|
foreach (var probe in probes)
|
|
{
|
|
var newProbeObj = Object.Instantiate(probe.gameObject, container.transform);
|
|
newProbeObj.name = $"[BG] {probe.gameObject.name}";
|
|
SceneManager.MoveGameObjectToScene(newProbeObj, targetScene);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void CopyLightProbeGroups(Scene sourceScene, Scene targetScene)
|
|
{
|
|
var sourceRoots = sourceScene.GetRootGameObjects();
|
|
var container = GetOrCreateLightingContainer(targetScene, "Background LightProbes");
|
|
|
|
foreach (var root in sourceRoots)
|
|
{
|
|
var groups = root.GetComponentsInChildren<LightProbeGroup>(true);
|
|
foreach (var group in groups)
|
|
{
|
|
var newGroupObj = Object.Instantiate(group.gameObject, container.transform);
|
|
newGroupObj.name = $"[BG] {group.gameObject.name}";
|
|
SceneManager.MoveGameObjectToScene(newGroupObj, targetScene);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void CopyVolumes(Scene sourceScene, Scene targetScene)
|
|
{
|
|
var sourceRoots = sourceScene.GetRootGameObjects();
|
|
var container = GetOrCreateLightingContainer(targetScene, "Background Volumes");
|
|
|
|
foreach (var root in sourceRoots)
|
|
{
|
|
var volumes = root.GetComponentsInChildren<Volume>(true);
|
|
foreach (var volume in volumes)
|
|
{
|
|
var newVolumeObj = Object.Instantiate(volume.gameObject, container.transform);
|
|
newVolumeObj.name = $"[BG] {volume.gameObject.name}";
|
|
SceneManager.MoveGameObjectToScene(newVolumeObj, targetScene);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static GameObject GetOrCreateLightingContainer(Scene scene, string name)
|
|
{
|
|
var roots = scene.GetRootGameObjects();
|
|
|
|
// 기존 컨테이너 찾기
|
|
foreach (var root in roots)
|
|
{
|
|
if (root.name == name)
|
|
{
|
|
// 기존 자식들 제거
|
|
while (root.transform.childCount > 0)
|
|
{
|
|
Object.DestroyImmediate(root.transform.GetChild(0).gameObject);
|
|
}
|
|
return root;
|
|
}
|
|
}
|
|
|
|
// 새 컨테이너 생성
|
|
var container = new GameObject(name);
|
|
SceneManager.MoveGameObjectToScene(container, scene);
|
|
return container;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 타겟 씬에서 복사된 라이팅 오브젝트들 제거
|
|
/// </summary>
|
|
public static void RemoveCopiedLighting(Scene targetScene)
|
|
{
|
|
var roots = targetScene.GetRootGameObjects();
|
|
var toRemove = new List<GameObject>();
|
|
|
|
foreach (var root in roots)
|
|
{
|
|
if (root.name.StartsWith("Background ") ||
|
|
root.name.StartsWith("[BG]"))
|
|
{
|
|
toRemove.Add(root);
|
|
}
|
|
}
|
|
|
|
foreach (var obj in toRemove)
|
|
{
|
|
Object.DestroyImmediate(obj);
|
|
}
|
|
|
|
UnityEngine.Debug.Log($"복사된 라이팅 오브젝트 제거됨: {toRemove.Count}개");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 배경 씬의 Skybox Material 가져오기
|
|
/// </summary>
|
|
public static Material GetSkyboxFromScene(Scene scene)
|
|
{
|
|
var roots = scene.GetRootGameObjects();
|
|
|
|
foreach (var root in roots)
|
|
{
|
|
// Skybox 컴포넌트가 있는 카메라 찾기
|
|
var cameras = root.GetComponentsInChildren<Camera>(true);
|
|
foreach (var cam in cameras)
|
|
{
|
|
var skybox = cam.GetComponent<Skybox>();
|
|
if (skybox != null && skybox.material != null)
|
|
{
|
|
return skybox.material;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// RenderSettings 전체 복사 (Skybox, Ambient, Fog 등)
|
|
/// </summary>
|
|
public static void ApplyRenderSettings(
|
|
Material skybox = null,
|
|
AmbientMode? ambientMode = null,
|
|
Color? ambientLight = null,
|
|
bool? fog = null,
|
|
Color? fogColor = null,
|
|
float? fogDensity = null)
|
|
{
|
|
if (skybox != null)
|
|
RenderSettings.skybox = skybox;
|
|
|
|
if (ambientMode.HasValue)
|
|
RenderSettings.ambientMode = ambientMode.Value;
|
|
|
|
if (ambientLight.HasValue)
|
|
RenderSettings.ambientLight = ambientLight.Value;
|
|
|
|
if (fog.HasValue)
|
|
RenderSettings.fog = fog.Value;
|
|
|
|
if (fogColor.HasValue)
|
|
RenderSettings.fogColor = fogColor.Value;
|
|
|
|
if (fogDensity.HasValue)
|
|
RenderSettings.fogDensity = fogDensity.Value;
|
|
}
|
|
}
|
|
}
|