114 lines
7.0 KiB
C#
114 lines
7.0 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// WLIslandLoadingFix.cs — 섬으로 들어갈 때 로딩창이 90 % 에서 멈추는 것을 푼다.
|
|
//
|
|
// ■ 원인 (Lead 가 PD 의 멈춘 화면에서 실측 · 2026-09-13)
|
|
// `LoadingUI.End_Loading(index)` 는 칸 2개가 **모두** 참이어야 로딩창을 닫는다.
|
|
// · 칸 1 = UI 준비 → `NewGameUI.cs:88` 이 채운다 → **True**
|
|
// · 칸 0 = 몬스터 프리팹 로드 → `MobControlMgrList.cs:28` 이 채운다 → **False**
|
|
// 섬(`Level01` · 맵 900)은 전투 맵이 아니라 **`MobControlMgrList` 가 아예 없다**
|
|
// (실측: 인스턴스 수 0). 그래서 칸 0 이 영원히 False → 로딩창이 안 닫힌다.
|
|
// 실측값: `list_loadingComplete = [False, True]` · 씬은 정상 로드(`Level01` root 15)
|
|
// · `bMyPC=True` · 풀·게이트·룩 전부 생성돼 있었다. **화면만 가려져 있었다.**
|
|
//
|
|
// ■ 조치
|
|
// 섬 씬이 붙은 뒤 `MobControlMgrList` 가 없으면 **우리가 칸 0 을 채운다**.
|
|
// 원본 파일 수정 0 — 씬 로드를 스스로 감시해 자기가 붙는다.
|
|
// 🔴 전투 맵에는 손대지 않는다(그쪽은 `MobControlMgrList` 가 정상적으로 채운다).
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace WL.Island
|
|
{
|
|
[DisallowMultipleComponent]
|
|
public sealed class WLIslandLoadingFix : MonoBehaviour
|
|
{
|
|
/// <summary>이 이름들의 씬이 붙으면 「몬스터 없는 맵」으로 본다.</summary>
|
|
static readonly string[] NoMobScenes = { "Level01", "Level02", "Level03", "WL_FarmLook" };
|
|
|
|
/// <summary>
|
|
/// 🔴 WL-816g — **던전 씬도 같은 문제다.** 던전(`WL_Dungeon01`·`02`)은 아레나 복사본이라
|
|
/// `MobControlMgrList` 가 **한 개도 없다**(실측: 세 씬 전부 0개 · `WL_ArenaProto` 포함).
|
|
/// 몹은 `StageDirector` 가 스테이지 시작 때 스포너로 만든다 — 로딩 칸 0 을 채워 줄 주인이 없다.
|
|
/// 이름을 더 적는 대신 **던전 표(`WLIslandSettings.dungeons[].sceneName`)를 그대로 본다** —
|
|
/// 표에 줄을 추가하면 그 씬도 자동으로 포함된다.
|
|
/// </summary>
|
|
static bool IsDungeonScene(string sceneName)
|
|
{
|
|
var cfg = WLIslandSettings.Instance;
|
|
if (cfg == null || cfg.enabled_ == 0) return false;
|
|
return cfg.FindBySceneName(sceneName) != null;
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
static void Hook()
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
}
|
|
|
|
static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
bool match = false;
|
|
for (int i = 0; i < NoMobScenes.Length; i++)
|
|
if (scene.name == NoMobScenes[i]) { match = true; break; }
|
|
if (!match) match = IsDungeonScene(scene.name);
|
|
if (!match) return;
|
|
|
|
bool dungeon = IsDungeonScene(scene.name);
|
|
var host = new GameObject("~WL_IslandLoadingFix");
|
|
host.hideFlags = HideFlags.HideAndDontSave;
|
|
host.AddComponent<WLIslandLoadingFix>().StartCoroutine(Run(host, dungeon));
|
|
}
|
|
|
|
static System.Collections.IEnumerator Run(GameObject host, bool dungeon)
|
|
{
|
|
// 원본이 스스로 채울 기회를 먼저 준다(전투 맵과 섞여 로드되는 경우 대비).
|
|
for (float t = 0f; t < 5f; t += Time.unscaledDeltaTime)
|
|
{
|
|
var mgrs = Object.FindObjectsByType<MobControlMgrList>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
if (mgrs != null && mgrs.Length > 0) { if (host != null) Destroy(host); yield break; } // 원본이 채운다 — 빠진다
|
|
|
|
if (LoadingUI.isIns)
|
|
{
|
|
// 🔴 WL-816l — 던전은 **카메라가 최종 구도에 앉을 때까지** 로딩 화면을 닫지 않는다.
|
|
// 원본 순서상 로딩 칸 1(NewGameUI.SetUI_byGameMode)은 `StartCam()` **바로 뒤**에 채워진다
|
|
// (SceneInfo.Co_Control_AddScene → addloadend → InGameInfo.Load_Map 의 람다 · 씬 로드 1 초 뒤).
|
|
// 그래서 여기서 칸 0 을 먼저 채워 두면 화면이 **카메라 연출과 같은 프레임에 열려** 튐이 그대로 보인다.
|
|
// 카메라 정착(WLDungeonCameraRig.Settled) + 스테이지 입장(EnterCalls) 뒤에 채우면
|
|
// PD 가 보는 첫 화면이 이미 최종 구도다. 상한(SO)을 넘기면 조건과 무관하게 채운다(무한 대기 방지).
|
|
if (dungeon) yield return WaitForCamera();
|
|
LoadingUI.Ins.End_Loading(0);
|
|
Debug.Log(dungeon
|
|
? ("[WL-816l] 던전 로딩 칸 0 — 카메라 정착 " + WLDungeonCameraRig.Settled +
|
|
" · 스냅 " + WLDungeonCameraRig.Snaps + " · 스테이지 입장 " + WLDungeonSceneSetup.EnterCalls + " 회 뒤에 채웠다")
|
|
: "[WL-816] 섬에는 MobControlMgrList 가 없어 로딩 칸 0 을 대신 채웠다(90% 멈춤 해소)");
|
|
if (host != null) Destroy(host);
|
|
yield break;
|
|
}
|
|
yield return null;
|
|
}
|
|
if (host != null) Destroy(host);
|
|
}
|
|
|
|
/// <summary>던전 전용 — 카메라가 최종 구도에 앉고 스테이지가 입장할 때까지 기다린다(상한 = SO).</summary>
|
|
static System.Collections.IEnumerator WaitForCamera()
|
|
{
|
|
var cfg = WLIslandSettings.Instance;
|
|
if (cfg == null || cfg.dungeonLoadingWaitForCamera == 0) yield break;
|
|
// 카메라 보정기 자체가 꺼져 있으면 기다릴 대상이 없다(= 816g 동작 그대로).
|
|
if (cfg.dungeonCameraMatchIsland == 0 || cfg.dungeonCamInstantSettle == 0) yield break;
|
|
int enterAtStart = WLDungeonSceneSetup.EnterCalls;
|
|
float limit = cfg.dungeonLoadingMaxWaitSeconds > 0f ? cfg.dungeonLoadingMaxWaitSeconds : 8f;
|
|
for (float t = 0f; t < limit; t += Time.unscaledDeltaTime)
|
|
{
|
|
if (WLDungeonCameraRig.Settled && WLDungeonSceneSetup.EnterCalls > enterAtStart) yield break;
|
|
yield return null;
|
|
}
|
|
Debug.Log("[WL-816l] 던전 로딩 대기 상한(" + limit.ToString("F1") + "s) 도달 — 정착 " +
|
|
WLDungeonCameraRig.Settled + " · 입장 " + (WLDungeonSceneSetup.EnterCalls - enterAtStart) + " 회");
|
|
}
|
|
}
|
|
}
|