82 lines
4.1 KiB
C#
82 lines
4.1 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// TelegraphRunner.cs — 815f 전용 틱 러너(숨은 오브젝트 1개 · DontDestroyOnLoad · 코루틴 없음 · GC 0)
|
|
//
|
|
// PD 지시 #815-5 · 발주서 WL-815f
|
|
//
|
|
// ■ 왜 ImpactRunner(811gh) · WLReactionRunner(811def) 에 얹지 않았나
|
|
// 같은 파일에 틱을 붙이면 **병합 충돌**이 난다(811gh 가 811i 때문에 파일을 나눈 것과 같은 이유).
|
|
// 새 Manager/Singleton 패러다임이 아니라 기존 러너와 **같은 패턴**을 하나 더 두는 것이다.
|
|
//
|
|
// ■ 무엇을 하나
|
|
// Telegraph.Tick — 데칼 위치·회전 추종 · 채워지는 진행 · 스케일 펄스 · 히트 직전 흰 섬광 · 타임아웃 원복.
|
|
// 파괴·비활성·앱 종료·씬 전환 시 애니메이터 속도 / 스케일 / MPB 색 / 데칼을 전부 원복한다.
|
|
//
|
|
// ■ 에디트 모드
|
|
// 프로브가 Play 없이 검증할 수 있게 ForceTick(delta) 를 둔다(러너 오브젝트 없이 같은 틱 1회 + 시뮬레이션 시계).
|
|
//
|
|
// 🔴 어셈블리 주의: Assets/WL/Combat/ 에 .asmdef 를 만들지 말 것.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace WL.Combat.Telegraph
|
|
{
|
|
public sealed class TelegraphRunner : MonoBehaviour
|
|
{
|
|
static TelegraphRunner s_runner;
|
|
static bool s_sceneHooked;
|
|
|
|
public static bool Exists { get { return s_runner != null; } }
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
static void Boot() { if (WLTelegraphSettings.Enabled) Ensure(); }
|
|
|
|
public static void Ensure()
|
|
{
|
|
if (s_runner != null) return;
|
|
if (!Application.isPlaying) return; // 에디트 모드에서는 오브젝트를 만들지 않는다(프로브는 ForceTick 을 쓴다)
|
|
var go = new GameObject("__WLTelegraph");
|
|
go.hideFlags = HideFlags.DontSave;
|
|
DontDestroyOnLoad(go);
|
|
s_runner = go.AddComponent<TelegraphRunner>();
|
|
if (!s_sceneHooked) { SceneManager.activeSceneChanged += OnSceneChanged; s_sceneHooked = true; }
|
|
}
|
|
|
|
static void OnSceneChanged(Scene from, Scene to) { Telegraph.ClearAll(); }
|
|
|
|
// ── 에디트 모드 시뮬레이션 시계(811gh ImpactRunner 와 같은 방식)
|
|
static float s_simNow;
|
|
static bool s_simActive;
|
|
|
|
/// <summary>연출 타이밍의 기준 시각. Play = Time.unscaledTime · 프로브(ForceTick) = 시뮬레이션 시계.</summary>
|
|
public static float Now { get { return s_simActive ? s_simNow : Time.unscaledTime; } }
|
|
|
|
void Update()
|
|
{
|
|
s_simActive = false;
|
|
Telegraph.Tick(Time.unscaledTime);
|
|
}
|
|
|
|
/// <summary>프로브(에디트 모드)용 — 러너 없이 같은 틱을 1회 돌리고 시뮬레이션 시계를 delta 만큼 민다.</summary>
|
|
public static void ForceTick(float unscaledDelta)
|
|
{
|
|
if (!s_simActive) { s_simActive = true; s_simNow = Time.unscaledTime; }
|
|
s_simNow += unscaledDelta;
|
|
Telegraph.Tick(s_simNow);
|
|
}
|
|
|
|
/// <summary>프로브용 — 시뮬레이션 시계를 켜기만 한다(이벤트를 올리기 전에 기준점을 고정).</summary>
|
|
public static void BeginForceClock()
|
|
{
|
|
if (!s_simActive) { s_simActive = true; s_simNow = Time.unscaledTime; }
|
|
}
|
|
|
|
/// <summary>프로브용 — 시뮬레이션 시계를 끄고 실제 시간으로 되돌린다.</summary>
|
|
public static void ResetForceClock() { s_simActive = false; s_simNow = 0f; }
|
|
|
|
void OnDisable() { Telegraph.RestoreAll(); }
|
|
void OnApplicationQuit() { Telegraph.RestoreAll(); }
|
|
}
|
|
}
|