2026-04-29 게임 로딩 개선
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -6,8 +6,12 @@ public class SoundManager : MonoBehaviour
|
||||
public static SoundManager Instance { get; private set; }
|
||||
|
||||
[SerializeField] private AudioSource _bgmSource;
|
||||
[SerializeField] private AudioSource _sfxSource;
|
||||
[SerializeField] private AudioMixer _mixer;
|
||||
|
||||
[Header("SFX")]
|
||||
[SerializeField] private AudioClip SFX_UIHover;
|
||||
|
||||
private const string BGM_VOLUME_PARAM = "BGMVolume";
|
||||
private const string SFX_VOLUME_PARAM = "SFXVolume";
|
||||
|
||||
@@ -26,6 +30,12 @@ private void OnDestroy()
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
|
||||
public void PlaySFX(AudioClip clip)
|
||||
{
|
||||
if(_sfxSource == null || clip == null) return;
|
||||
_sfxSource.PlayOneShot(clip);
|
||||
}
|
||||
|
||||
public void PlayBGM(AudioClip clip)
|
||||
{
|
||||
if (_bgmSource == null || clip == null) return;
|
||||
@@ -75,4 +85,9 @@ private void SetMixerVolume(string parameter, float linear)
|
||||
float db = linear > 0.0001f ? Mathf.Log10(linear) * 20f : -80f;
|
||||
_mixer.SetFloat(parameter, db);
|
||||
}
|
||||
|
||||
public void SFXPlay_UIHover()
|
||||
{
|
||||
PlaySFX(SFX_UIHover);
|
||||
}
|
||||
}
|
||||
|
||||
8
Assets/02_Scripts/Sound.meta
Normal file
8
Assets/02_Scripts/Sound.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1958a2981c9c13f4fa08c614e668e2fa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/02_Scripts/Sound/BGMObject.cs
Normal file
16
Assets/02_Scripts/Sound/BGMObject.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class BGMObject : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/02_Scripts/Sound/BGMObject.cs.meta
Normal file
2
Assets/02_Scripts/Sound/BGMObject.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01702c6baeb850b4593ebc1dc16a0a3b
|
||||
@@ -11,18 +11,21 @@ public class BGMBox : MonoBehaviour
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_bgmNameField.text = _bgmClip.BGMName;
|
||||
if(_bgmNameField != null)
|
||||
_bgmNameField.text = _bgmClip.BGMName;
|
||||
}
|
||||
|
||||
public void PlayBGM()
|
||||
{
|
||||
SoundManager.Instance.PlayBGM(_bgmClip.Clip);
|
||||
_playSignObj.SetActive(true);
|
||||
if(_playSignObj != null)
|
||||
_playSignObj.SetActive(true);
|
||||
}
|
||||
|
||||
public void StopBGM()
|
||||
{
|
||||
SoundManager.Instance.StopBGM();
|
||||
_playSignObj.SetActive(false);
|
||||
if(_playSignObj != null)
|
||||
_playSignObj.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public class BGMHud : MonoBehaviour
|
||||
[SerializeField] private GameObject _contentPrefab;
|
||||
|
||||
private BGMBox currentBgm;
|
||||
[SerializeField]private BGMClip DefaultBgm;
|
||||
[SerializeField] private BGMClip DefaultBgm;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user