diff --git a/Assets/WL/Island/WLIslandPcEventSilencer.cs b/Assets/WL/Island/WLIslandPcEventSilencer.cs new file mode 100644 index 000000000..65e33eddf --- /dev/null +++ b/Assets/WL/Island/WLIslandPcEventSilencer.cs @@ -0,0 +1,82 @@ +// ───────────────────────────────────────────────────────────────────────────── +// WLIslandPcEventSilencer.cs — 섬 전시용 캐릭터(`~WL_IslandPcVisual`)의 +// 애니메이션 이벤트를 잠재운다. +// +// ■ 왜 필요한가 (Lead 실측 · 2026-09-13) +// PD 보고 에러: `'~WL_IslandPcVisual' AnimationEvent 'OnStep' on animation 'Run' +// has no receiver!` +// · `WLIslandPcRig.Bind()` 가 FarmingIsland 플레이어의 `runtimeAnimatorController` +// 를 **우리 치비 비주얼의 Animator 에 복사**해 같은 클립을 함께 재생한다(816d). +// · FI 의 `Run` 클립은 `OnStep` 을, 농사 클립은 `OnPlant`/`OnHarvest` 를 쏜다 +// (`FarmingIsland/Scripts/Core/PlayerController.cs:243` 등). +// · 🔴 유니티는 애니메이션 이벤트를 **Animator 와 같은 GameObject 의 컴포넌트에만** +// 보낸다. 수신자 `PlayerController` 는 **부모(FI Player)** 에 있고 비주얼 자식에는 +// 없다 → 프레임마다 「has no receiver!」. +// +// ■ 왜 「무시」가 맞는가 +// 부모의 Animator 도 같은 클립을 돌며 **그쪽에서 이미 `PlayerController` 로 이벤트가 +// 간다**(발소리는 정상 재생된다). 비주얼 쪽 이벤트는 **중복**이므로 받으면 오히려 +// 발소리가 두 번 난다. 그래서 수신자를 만들지 않고 **발사 자체를 끈다**. +// +// ■ 기존 파일 0줄 수정 — 씬 로드를 스스로 감시해 자기가 붙는다. +// ───────────────────────────────────────────────────────────────────────────── + +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace WL.Island +{ + [DisallowMultipleComponent] + public sealed class WLIslandPcEventSilencer : MonoBehaviour + { + const string PcVisualName = "~WL_IslandPcVisual"; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + static void Hook() + { + SceneManager.sceneLoaded -= OnSceneLoaded; + SceneManager.sceneLoaded += OnSceneLoaded; + for (int i = 0; i < SceneManager.sceneCount; i++) + { + var sc = SceneManager.GetSceneAt(i); + if (sc.isLoaded) OnSceneLoaded(sc, LoadSceneMode.Additive); + } + } + + static void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + // 비주얼은 FI 플레이어가 생긴 뒤에 붙는다 — 몇 프레임 감시한다. + var host = new GameObject("~WL_IslandPcEventSilencer"); + host.hideFlags = HideFlags.HideAndDontSave; + host.AddComponent().StartCoroutine(Watch(host)); + } + + static System.Collections.IEnumerator Watch(GameObject host) + { + // 최대 10초. 찾으면 끄고 자신도 사라진다. + for (float t = 0f; t < 10f; t += Time.unscaledDeltaTime) + { + var visual = Find(PcVisualName); + if (visual != null) + { + int n = 0; + foreach (var a in visual.GetComponentsInChildren(true)) + { + if (a.fireEvents) { a.fireEvents = false; n++; } + } + if (n > 0) Debug.Log("[WL-816] 섬 비주얼 애니메이션 이벤트 " + n + "개 Animator 에서 차단(중복 방지)"); + break; + } + yield return null; + } + if (host != null) Destroy(host); + } + + static Transform Find(string name) + { + foreach (var go in Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None)) + if (go.name == name) return go.transform; + return null; + } + } +} diff --git a/Assets/WL/Island/WLIslandPcEventSilencer.cs.meta b/Assets/WL/Island/WLIslandPcEventSilencer.cs.meta new file mode 100644 index 000000000..125a80156 --- /dev/null +++ b/Assets/WL/Island/WLIslandPcEventSilencer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 65467b378e345fb4eb9177a2a9f534ec \ No newline at end of file