diff --git a/Assets/WL/Look/Arena/ArenaWalker.cs b/Assets/WL/Look/Arena/ArenaWalker.cs
new file mode 100644
index 000000000..ca02ffe9a
--- /dev/null
+++ b/Assets/WL/Look/Arena/ArenaWalker.cs
@@ -0,0 +1,153 @@
+// ─────────────────────────────────────────────────────────────────────────────
+// 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";
+
+ [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;
+
+ void Start()
+ {
+ 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);
+ }
+
+ 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 (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;
+ 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}