[WL-816] 섬 캐릭터 애니메이션 이벤트 중복 차단 — 'OnStep has no receiver' 제거 (#816)
PD 보고: 'OnStep' on animation 'Run' has no receiver! 원인(실측): WLIslandPcRig 가 FI 플레이어의 컨트롤러를 우리 치비 비주얼의 Animator 에 복사해 같은 클립을 함께 돌린다(816d). FI 의 Run 클립이 쏘는 OnStep 의 수신자 PlayerController(FarmingIsland/Scripts/Core/PlayerController.cs:243) 는 부모에 있는데, 유니티는 애니메이션 이벤트를 Animator 와 같은 GameObject 에만 보낸다 → 비주얼 자식에서 수신자 없음. 부모 Animator 가 이미 같은 이벤트를 PlayerController 로 보내 발소리는 정상 재생된다. 비주얼 쪽은 중복이므로 수신자를 만들면 발소리가 두 번 난다 → 비주얼 Animator 의 fireEvents 만 끈다. 기존 파일 0줄 수정(자가 부착). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
a2a954ba83
commit
f04ac8cfb6
|
|
@ -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<WLIslandPcEventSilencer>().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<Animator>(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<GameObject>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||
if (go.name == name) return go.transform;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 65467b378e345fb4eb9177a2a9f534ec
|
||||
Loading…
Reference in New Issue