2026-04-29 게임 로딩 개선

This commit is contained in:
2026-04-29 18:42:59 +09:00
parent b626a1b5e6
commit dfb5857642
31 changed files with 1230 additions and 10 deletions

View File

@@ -11,6 +11,17 @@ public class SceneLoadManager : MonoBehaviour
[SerializeField] private Transform _loadingCamTargetTransform;
[SerializeField] private LoadingScreen _loadingScreen;
[SerializeField] private Material _supermarketStartSkybox;
[SerializeField] private Material _supermarketLoadingSkybox;
[SerializeField, Min(0f)] private float _skyboxFadeTime = 1f;
// 정상(밝음) 상태에서의 스카이박스 _Exposure 값. 페이드 인의 도착 지점.
[SerializeField, Min(0f)] private float _skyboxNormalExposure = 1f;
// 공유 에셋이 더러워지지 않도록 런타임 인스턴스로 복제해 사용
private Material _runtimeStartSkybox;
private Material _runtimeLoadingSkybox;
private void Awake()
{
if (Instance == null)
@@ -23,6 +34,24 @@ private void Awake()
}
_loadingScreen = _loadingCam.GetComponentInChildren<LoadingScreen>();
if (_supermarketStartSkybox != null)
_runtimeStartSkybox = new Material(_supermarketStartSkybox);
if (_supermarketLoadingSkybox != null)
_runtimeLoadingSkybox = new Material(_supermarketLoadingSkybox);
if (_runtimeStartSkybox != null)
{
RenderSettings.skybox = _runtimeStartSkybox;
DynamicGI.UpdateEnvironment();
}
}
private void OnDestroy()
{
// 런타임 복제 인스턴스는 직접 정리
if (_runtimeStartSkybox != null) Destroy(_runtimeStartSkybox);
if (_runtimeLoadingSkybox != null) Destroy(_runtimeLoadingSkybox);
}
private void Start()
@@ -77,7 +106,27 @@ public async Awaitable FadeLoadingCanvas(bool isOut,float fadeTime)
_loadingScreen.LoadingScreenCanvasGroup.alpha = endAlpha;
}
public async Task SetSceneLoadingActive(bool isActive,float alphaTime)
// 현재 RenderSettings.skybox의 _Exposure를 from→to로 보간
// Skybox/Procedural, /Cubemap, /Panoramic 셰이더 공통 프로퍼티
private async Awaitable FadeSkybox(float from, float to, float duration)
{
var sky = RenderSettings.skybox;
if (sky == null || !sky.HasFloat("_Exposure")) return;
float timer = 0f;
while (timer < duration)
{
timer += Time.deltaTime;
float k = Mathf.Clamp01(timer / duration);
sky.SetFloat("_Exposure", Mathf.Lerp(from, to, k));
DynamicGI.UpdateEnvironment();
await Awaitable.NextFrameAsync(this.destroyCancellationToken);
}
sky.SetFloat("_Exposure", to);
DynamicGI.UpdateEnvironment();
}
public async Awaitable SetSceneLoadingActive(bool isActive,float alphaTime)
{
if (isActive)
_loadingRoot.SetActive(true);
@@ -118,6 +167,15 @@ private async Awaitable SceneChange(string sceneName)
{
SetSceneLoadingProgressValue(0f);
//스카이 박스 페이드 아웃 로직
await FadeSkybox(_skyboxNormalExposure, 0f, _skyboxFadeTime);
// 검게 된 상태에서 머티리얼 교체 (교체 순간이 가려져 깜빡임 없음)
RenderSettings.skybox = _runtimeLoadingSkybox;
//스카이 박스 페이드 인 로직
await FadeSkybox(0f, _skyboxNormalExposure, _skyboxFadeTime);
await SetSceneLoadingActive(true,1f);
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
@@ -148,6 +206,14 @@ private async Awaitable SceneChange(string sceneName)
// 잠시 대기했다가 전환
await Awaitable.WaitForSecondsAsync(1.0f, this.destroyCancellationToken);
await SetSceneLoadingActive(false,1f);
//스카이 박스 페이드 아웃
await FadeSkybox(_skyboxNormalExposure, 0f, _skyboxFadeTime);
// 검게 된 상태에서 정상 스카이박스로 교체
RenderSettings.skybox = _runtimeStartSkybox;
//로딩 끝
op.allowSceneActivation = true;
@@ -161,9 +227,11 @@ private async Awaitable SceneChange(string sceneName)
//VR용 로직
//트래킹이 중단되면 안되기 때문에 카메라를 유지해야 한다
_loadingCamTargetTransform = Camera.main.transform; // 새로운 씬의 메인카메라를 따라가게끔 설정
await SetSceneLoadingActive(false,1f);
//-------------------------------------------------------------------------------
//스카이 박스 페이드 인
await FadeSkybox(0f, _skyboxNormalExposure, _skyboxFadeTime);
Debug.Log("씬 전환됨");
}
catch (OperationCanceledException)