From 4f2fdb0a86bc04a17b30d835bf6986d22bad5618 Mon Sep 17 00:00:00 2001 From: swrring Date: Sat, 12 Sep 2026 21:52:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[WL-814r]=20=EC=8B=9C=EB=B2=94=20=EC=A0=84?= =?UTF-8?q?=ED=88=AC=EC=9E=A5=20Play=20=EC=97=90=EB=9F=AC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20+=20=EB=8D=B0=EB=AA=A8=20=EC=B9=B4=EB=A9=94?= =?UTF-8?q?=EB=9D=BC=20=EC=9D=B4=EC=8B=9D=20+=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EB=A6=AC=EA=B7=B8=20(#814)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PC_LH_M05 씬 인스턴스에서 게임 컴포넌트 7종 제거(WizardActor·NavMeshAgent· Rigidbody·CapsuleCollider·SkinnedMeshAfterImage·WLPcScaleCompensator· WLWeaponFitter) → 게임 초기화 없이 Update 가 돌며 터지던 KeyNotFoundException: 'Freeze'(Actor.cs:1065) 제거. 프리팹 수정 0. 루트 스케일 1.05266 · 몸 높이 1.21651 m 는 제거 전후 델타 0 실측. - Main Camera 를 Demo.unity 실측값으로 이식: 직교 size 10 · euler(30,60,0) · near 0.3 / far 500 · clear Skybox · depth -1 · HDR/MSAA on + UniversalAdditionalCameraData(post off · AA none · rendererIndex -1). - 씬 라이트 3개에 UniversalAdditionalLightData 추가(데모와 동일 구성). - Terrain.drawTreesAndFoliage false→true(데모와 동일). - ArenaWalker.cs(신규 · 씬 전용): WASD 이동 + 방향 회전 + idle/run 상태 재생 + 카메라 추적 + Terrain.SampleHeight 접지. 속도 3.9 / 회전 300 은 LH_M05.prefab NavMeshAgent 실측값. Co-Authored-By: Claude Opus 5 --- Assets/WL/Look/Arena/ArenaWalker.cs | 126 +++++++++++ Assets/WL/Look/Arena/ArenaWalker.cs.meta | 2 + .../WL/Look/Arena/Scenes/WL_ArenaProto.unity | 211 +++++++++++++++++- 3 files changed, 333 insertions(+), 6 deletions(-) create mode 100644 Assets/WL/Look/Arena/ArenaWalker.cs create mode 100644 Assets/WL/Look/Arena/ArenaWalker.cs.meta diff --git a/Assets/WL/Look/Arena/ArenaWalker.cs b/Assets/WL/Look/Arena/ArenaWalker.cs new file mode 100644 index 000000000..2a32a5d4b --- /dev/null +++ b/Assets/WL/Look/Arena/ArenaWalker.cs @@ -0,0 +1,126 @@ +// ───────────────────────────────────────────────────────────────────────────── +// ArenaWalker.cs — 시범 전투장(WL_ArenaProto) 전용 이동 리그 (발주서 WL-814r · PD 「걸어다니며 크기 감 잡기」) +// +// ■ 왜 새 스크립트인가 +// 이 씬의 캐릭터는 **전시용**이라 게임 컴포넌트(`WizardActor`·`NavMeshAgent`·`Rigidbody`·`CapsuleCollider`)를 +// 전부 떼어 냈다(814r §1 · 그것들이 게임 초기화 없이 돌면서 `KeyNotFoundException: 'Freeze'` 가 프레임마다 터졌다). +// 되살리면 에러 0 이 깨지므로, **본편 시스템을 전혀 건드리지 않는 씬 전용 리그**를 따로 둔다. +// +// ■ 캐릭터에 붙이지 않고 별도 오브젝트에 두는 이유 +// `PC_LH_M05` 는 프리팹 인스턴스다. 거기에 컴포넌트를 더하면 「전시용 = Transform·Animator·렌더러뿐」이라는 +// 814r §1 의 완료 조건이 흐려진다. 그래서 이 리그가 밖에서 `body` 를 움직인다(프리팹 수정 0 · 인스턴스 추가 0). +// +// ■ 실측해서 가져온 값 (하드코딩 아님 · 전부 인스펙터 노출 · 출처 주석) +// · moveSpeed 3.9 = `Assets/Res_Addr/PC/LH_M05.prefab` NavMeshAgent `m_Speed` (인게임 이동 속도 그대로) +// · turnSpeed 300 = 같은 프리팹 NavMeshAgent `m_AngularSpeed` +// · 애니메이션 전환 = 원본 `Actor.AnimationPlay()` 가 쓰는 **상태 이름 직접 재생** 방식 그대로 +// (`Assets/Script/Character/Actor.cs:2031` `m_animation.Play(aniname)` · 이름은 `MyValue.cs:72` +// `eAnim.Idle→"idle"` / `eAnim.Run→"run"` · `pcanim_mage.controller` 에 두 상태 모두 존재 실측). +// 🔴 이 컨트롤러의 Base Layer 에는 idle/run 으로 들어가는 **트랜지션이 없다** — 파라미터로는 못 바꾼다. +// +// ■ 바닥 +// 콜라이더를 전부 뗐으므로 물리를 쓰지 않는다. 지형 높이는 `Terrain.SampleHeight()` 로 직접 샘플링한다 +// (TerrainCollider 유무와 무관 · Raycast 보다 싸다). 바위·물 통과는 크기 확인용이라 신경 쓰지 않는다(발주 명시). +// +// ■ 입력 = 레거시 Input (이 프로젝트 `activeInputHandler: 0`) +// ───────────────────────────────────────────────────────────────────────────── + +using UnityEngine; + +namespace WL.Look.Arena +{ + [DisallowMultipleComponent] + public sealed class ArenaWalker : MonoBehaviour + { + [Header("대상")] + [Tooltip("움직일 캐릭터 루트. 비우면 이 오브젝트 자신.")] + public Transform body; + + [Tooltip("따라다닐 카메라. 비우면 Camera.main.")] + public Camera followCamera; + + [Header("이동 (LH_M05.prefab NavMeshAgent 실측값)")] + [Tooltip("m/s · NavMeshAgent.m_Speed = 3.9")] + public float moveSpeed = 3.9f; + + [Tooltip("deg/s · NavMeshAgent.m_AngularSpeed = 300")] + public float turnSpeed = 300f; + + [Header("애니메이션 상태 이름 (MyValue.cs:72)")] + public string idleState = "idle"; + public string runState = "run"; + + Animator _anim; + Vector3 _camOffset; + bool _running; + + void Start() + { + if (body == null) body = transform; + if (followCamera == null) followCamera = Camera.main; + _anim = body.GetComponentInChildren(); + if (followCamera != null) _camOffset = followCamera.transform.position - body.position; + SnapToGround(); + PlayState(idleState); + } + + void Update() + { + if (body == null) return; + + // 카메라 기준 입력(화면에서 보이는 방향대로 움직인다) + Vector3 fwd = Vector3.forward, right = Vector3.right; + if (followCamera != null) + { + fwd = Vector3.ProjectOnPlane(followCamera.transform.forward, Vector3.up); + if (fwd.sqrMagnitude < 1e-6f) fwd = Vector3.forward; + fwd.Normalize(); + right = Vector3.Cross(Vector3.up, fwd); + } + + Vector3 dir = right * Input.GetAxisRaw("Horizontal") + fwd * Input.GetAxisRaw("Vertical"); + if (dir.sqrMagnitude > 1f) dir.Normalize(); + + bool moving = dir.sqrMagnitude > 1e-4f; + if (moving) + { + body.position += dir * (moveSpeed * Time.deltaTime); + body.rotation = Quaternion.RotateTowards( + body.rotation, Quaternion.LookRotation(dir, Vector3.up), turnSpeed * Time.deltaTime); + } + SnapToGround(); + + if (moving != _running) + { + _running = moving; + PlayState(moving ? runState : idleState); + } + } + + void LateUpdate() + { + if (followCamera != null && body != null) + followCamera.transform.position = body.position + _camOffset; + } + + void SnapToGround() + { + var t = Terrain.activeTerrain; + if (t == null) return; + var p = body.position; + p.y = t.SampleHeight(p) + t.transform.position.y; + body.position = p; + } + + void PlayState(string state) + { + if (_anim != null && !string.IsNullOrEmpty(state)) _anim.Play(state, 0, 0f); + } + + /// 프로브용 — 지금까지 중앙(원점)에서 떨어진 수평 거리(m). + public float DistanceFromCenter + { + get { var p = body != null ? body.position : transform.position; return new Vector2(p.x, p.z).magnitude; } + } + } +} diff --git a/Assets/WL/Look/Arena/ArenaWalker.cs.meta b/Assets/WL/Look/Arena/ArenaWalker.cs.meta new file mode 100644 index 000000000..e32450f79 --- /dev/null +++ b/Assets/WL/Look/Arena/ArenaWalker.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8767c514397da294b856789af586ae40 \ No newline at end of file diff --git a/Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity b/Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity index b44112096..35d018093 100644 --- a/Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity +++ b/Assets/WL/Look/Arena/Scenes/WL_ArenaProto.unity @@ -7264,11 +7264,24 @@ PrefabInstance: propertyPath: m_LocalRotation.z value: -0.1736205 objectReference: {fileID: 0} - m_RemovedComponents: [] + m_RemovedComponents: + - {fileID: 8641894914256534733, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 7018224718987816087, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 2857479151170562952, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 3657923760099891804, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 1835281278008071509, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 1155056168462878929, guid: 13b0aeca987980646af87711964339c8, type: 3} + - {fileID: 8835979289890761207, guid: 13b0aeca987980646af87711964339c8, type: 3} m_RemovedGameObjects: [] m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 13b0aeca987980646af87711964339c8, type: 3} +--- !u!4 &918041735 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5000001850263733008, guid: 13b0aeca987980646af87711964339c8, + type: 3} + m_PrefabInstance: {fileID: 918041734} + m_PrefabAsset: {fileID: 0} --- !u!1001 &929833716 PrefabInstance: m_ObjectHideFlags: 0 @@ -7724,6 +7737,7 @@ GameObject: m_Component: - component: {fileID: 1021739863} - component: {fileID: 1021739864} + - component: {fileID: 1021739865} m_Layer: 0 m_Name: Directional Light m_TagString: Untagged @@ -7811,6 +7825,35 @@ Light: m_LightUnit: 1 m_LuxAtDistance: 1 m_EnableSpotReflector: 1 +--- !u!114 &1021739865 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1021739862} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalLightData + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_CustomShadowLayers: 0 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 + m_RenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_ShadowRenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_Version: 4 + m_LightLayerMask: 1 + m_ShadowLayerMask: 1 + m_RenderingLayers: 1 + m_ShadowRenderingLayers: 1 --- !u!1001 &1023981080 PrefabInstance: m_ObjectHideFlags: 0 @@ -8913,6 +8956,7 @@ GameObject: - component: {fileID: 1166334010} - component: {fileID: 1166334009} - component: {fileID: 1166334008} + - component: {fileID: 1166334011} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -8963,8 +9007,8 @@ Camera: far clip plane: 500 field of view: 60 orthographic: 1 - orthographic size: 3.4 - m_Depth: 0 + orthographic size: 10 + m_Depth: -1 m_CullingMask: serializedVersion: 2 m_Bits: 4294967295 @@ -8987,13 +9031,57 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1166334007} serializedVersion: 2 - m_LocalRotation: {x: -0.064500555, y: 0.9143501, z: -0.36580086, w: -0.1612246} - m_LocalPosition: {x: 1.5702481, y: 5.4334784, z: 4.3142214} + m_LocalRotation: {x: 0.22414388, y: 0.48296294, z: -0.12940954, w: 0.8365163} + m_LocalPosition: {x: -22.499998, y: 15.599999, z: -12.990381} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1166334011 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1166334007} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalCameraData + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!1001 &1169602851 PrefabInstance: m_ObjectHideFlags: 0 @@ -12037,7 +12125,7 @@ Terrain: m_ShadowCastingMode: 2 m_DrawHeightmap: 1 m_DrawInstanced: 0 - m_DrawTreesAndFoliage: 0 + m_DrawTreesAndFoliage: 1 m_StaticShadowCaster: 0 m_IgnoreQualitySettings: 0 m_ReflectionProbeUsage: 1 @@ -12258,6 +12346,7 @@ GameObject: m_Component: - component: {fileID: 1711927570} - component: {fileID: 1711927571} + - component: {fileID: 1711927572} m_Layer: 0 m_Name: Point Light 0 m_TagString: Untagged @@ -12345,6 +12434,35 @@ Light: m_LightUnit: 1 m_LuxAtDistance: 1 m_EnableSpotReflector: 1 +--- !u!114 &1711927572 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1711927569} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalLightData + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_CustomShadowLayers: 0 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 + m_RenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_ShadowRenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_Version: 4 + m_LightLayerMask: 1 + m_ShadowLayerMask: 1 + m_RenderingLayers: 1 + m_ShadowRenderingLayers: 1 --- !u!1001 &1731050756 PrefabInstance: m_ObjectHideFlags: 0 @@ -13067,6 +13185,7 @@ GameObject: m_Component: - component: {fileID: 1861768068} - component: {fileID: 1861768069} + - component: {fileID: 1861768070} m_Layer: 0 m_Name: Point Light 1 m_TagString: Untagged @@ -13154,6 +13273,35 @@ Light: m_LightUnit: 1 m_LuxAtDistance: 1 m_EnableSpotReflector: 1 +--- !u!114 &1861768070 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1861768067} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalLightData + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_CustomShadowLayers: 0 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 + m_RenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_ShadowRenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_Version: 4 + m_LightLayerMask: 1 + m_ShadowLayerMask: 1 + m_RenderingLayers: 1 + m_ShadowRenderingLayers: 1 --- !u!1001 &1867996742 PrefabInstance: m_ObjectHideFlags: 0 @@ -14359,6 +14507,56 @@ Transform: type: 3} m_PrefabInstance: {fileID: 2040128716} m_PrefabAsset: {fileID: 0} +--- !u!1 &2042308454 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2042308456} + - component: {fileID: 2042308455} + m_Layer: 0 + m_Name: ArenaWalkerRig + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2042308455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2042308454} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8767c514397da294b856789af586ae40, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::WL.Look.Arena.ArenaWalker + body: {fileID: 918041735} + followCamera: {fileID: 1166334009} + moveSpeed: 3.9 + turnSpeed: 300 + idleState: idle + runState: run +--- !u!4 &2042308456 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2042308454} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &2110215298 PrefabInstance: m_ObjectHideFlags: 0 @@ -14549,3 +14747,4 @@ SceneRoots: - {fileID: 1881675720} - {fileID: 918041734} - {fileID: 1166334010} + - {fileID: 2042308456} From 80453d64a05a05a9006e769eda3249f3f628b88c Mon Sep 17 00:00:00 2001 From: swrring Date: Sat, 12 Sep 2026 22:04:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[WL-814r]=20=EC=A0=84=EC=8B=9C=20=EC=BA=90?= =?UTF-8?q?=EB=A6=AD=ED=84=B0=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20+=20=EC=9D=B4=EB=8F=99=20=EC=86=8C?= =?UTF-8?q?=EC=9A=94=EC=8B=9C=EA=B0=84=20=ED=94=84=EB=A1=9C=EB=B8=8C=20(#8?= =?UTF-8?q?14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Animator.fireEvents=false: 클립 Idle 이 쏘는 Event_Idle 의 수신자(WizardActor)를 §1 에서 떼어 내 "AnimationEvent … has no receiver!" 가 2초마다 났다(실측 6회/12초). 빈 수신자 컴포넌트를 붙이는 대신 이벤트 발사를 끈다 → Play 콘솔 error 0. - autoWalk 프로브(기본 off): 중앙→14 m 소요 시간을 실측하기 위한 씬 전용 스위치. Co-Authored-By: Claude Opus 5 --- Assets/WL/Look/Arena/ArenaWalker.cs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Assets/WL/Look/Arena/ArenaWalker.cs b/Assets/WL/Look/Arena/ArenaWalker.cs index 2a32a5d4b..ca02ffe9a 100644 --- a/Assets/WL/Look/Arena/ArenaWalker.cs +++ b/Assets/WL/Look/Arena/ArenaWalker.cs @@ -50,6 +50,16 @@ namespace WL.Look.Arena public string idleState = "idle"; public string runState = "run"; + [Header("프로브 — 중앙→가장자리 소요 시간 실측용 (평소 off)")] + [Tooltip("켜면 입력 없이 autoWalkDir 로 자동 전진하고, 중앙에서 autoWalkGoal m 떨어지면 걸린 시간을 로그로 남긴다.")] + public bool autoWalk; + public Vector3 autoWalkDir = Vector3.right; + public float autoWalkGoal = 14f; + + float _autoT = -1f; + /// 자동 전진이 목표 거리에 도달한 시각(초). 아직이면 -1. + public float AutoWalkSeconds { get; private set; } = -1f; + Animator _anim; Vector3 _camOffset; bool _running; @@ -59,6 +69,13 @@ namespace WL.Look.Arena if (body == null) body = transform; if (followCamera == null) followCamera = Camera.main; _anim = body.GetComponentInChildren(); + + // 🔴 전시용 캐릭터에는 애니메이션 이벤트 수신자가 없다. + // 클립 `Idle` 이 `Event_Idle` 을 쏘는데 받는 쪽(`WizardActor`)을 떼어 냈으므로 + // 루프마다 "AnimationEvent 'Event_Idle' … has no receiver!" 에러가 난다(실측 2초에 1회). + // 빈 수신자 컴포넌트를 새로 붙이는 대신 이벤트 발사 자체를 끈다(런타임 전용 플래그). + foreach (var a in body.GetComponentsInChildren(true)) a.fireEvents = false; + if (followCamera != null) _camOffset = followCamera.transform.position - body.position; SnapToGround(); PlayState(idleState); @@ -79,6 +96,16 @@ namespace WL.Look.Arena } Vector3 dir = right * Input.GetAxisRaw("Horizontal") + fwd * Input.GetAxisRaw("Vertical"); + if (autoWalk && AutoWalkSeconds < 0f) + { + if (_autoT < 0f) _autoT = Time.time; + dir = autoWalkDir; + if (DistanceFromCenter >= autoWalkGoal) + { + AutoWalkSeconds = Time.time - _autoT; + Debug.Log(string.Format("[WL-814r] 중앙→{0:F1} m 도달: {1:F2} 초 (speed {2} m/s)", autoWalkGoal, AutoWalkSeconds, moveSpeed)); + } + } if (dir.sqrMagnitude > 1f) dir.Normalize(); bool moving = dir.sqrMagnitude > 1e-4f;