using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을 // ============================================================ // NorcielBoss.Movement.cs — NavMesh 에이전트 제어 + 회전/거리 유틸 (partial class) // // [역할] // ① NavMesh 에이전트 시작/정지/상태 확인 // ② 타겟 방향 부드러운 회전 (FaceTarget) // ③ 플레이어까지 거리 계산 (GetDist) // // [설계] // partial class로 NorcielBoss의 agent, _target 등 필드에 직접 접근. // FSM, 패턴 코루틴 등 여러 partial에서 공통으로 호출됩니다. // ============================================================ public partial class NorcielBoss : MonsterClass // 부분 클래스를 선언할거에요 -> NorcielBoss의 이동 유틸 부분으로 { // ══════════════════════════════════════════════════════════ // NavMesh 에이전트 제어 // ══════════════════════════════════════════════════════════ /// NavMesh 에이전트가 사용 가능한 상태인지 확인 private bool CheckNavMeshReady() // 함수를 선언할거에요 -> NavMesh 사용 가능한지 확인하는 { return agent != null && agent.enabled && agent.isOnNavMesh; // 반환할거에요 -> 사용 가능 여부를 } /// NavMesh 에이전트 활성화 + 이동 시작 private void StartAgent() // 함수를 선언할거에요 -> NavMesh 에이전트를 시작하는 { if (agent == null) return; // 중단할거에요 -> 없으면 if (!agent.enabled) agent.enabled = true; // 켤거에요 -> 비활성이면 if (agent.isOnNavMesh) agent.isStopped = false; // 켤거에요 -> NavMesh 위면 이동 시작 } /// NavMesh 에이전트 정지 + 관성 제거 private void StopAgent() // 함수를 선언할거에요 -> NavMesh 에이전트를 정지하는 { if (!CheckNavMeshReady()) return; // 중단할거에요 -> 비정상이면 agent.isStopped = true; // 멈출거에요 -> 이동을 agent.velocity = Vector3.zero; // 제거할거에요 -> 관성을 } // ══════════════════════════════════════════════════════════ // 회전 유틸리티 // ══════════════════════════════════════════════════════════ /// 타겟(또는 지정 위치) 방향으로 회전 (Y축 고정) /// null이면 _target 위치 사용 /// true면 즉시 스냅 회전, false면 Slerp 부드러운 회전 private void FaceTarget(Vector3? overridePos = null, bool instant = false) // 함수를 선언할거에요 -> 목표 방향으로 회전하는 (instant=true면 즉시 스냅) { Vector3 pos = overridePos ?? (_target != null ? _target.position : (Vector3?)null) ?? transform.position + transform.forward; // 결정할거에요 -> 바라볼 위치를 Vector3 dir = pos - transform.position; // 계산할거에요 -> 방향 벡터를 dir.y = 0f; // 제거할거에요 -> 높이 성분을 (수평 회전만) if (dir.sqrMagnitude > 0.001f) // 조건이 맞으면 실행할거에요 -> 방향 있으면 { Quaternion targetRot = Quaternion.LookRotation(dir); // 계산할거에요 -> 목표 회전을 if (instant) // 조건이 맞으면 실행할거에요 -> 즉시 스냅이면 transform.rotation = targetRot; // 스냅할거에요 -> 즉시 목표 방향으로 (1프레임에 완전 회전) else // 조건이 틀리면 실행할거에요 -> 부드러운 회전이면 transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, Time.deltaTime * 8f); // 회전할거에요 -> 부드럽게 } } // ══════════════════════════════════════════════════════════ // 거리 유틸리티 // ══════════════════════════════════════════════════════════ /// 현재 타겟(플레이어)까지의 거리 반환 — 타겟 없으면 9999 private float GetDist() // 함수를 선언할거에요 -> 플레이어까지 거리를 반환하는 { if (_target == null) return 9999f; // 반환할거에요 -> 타겟 없으면 최대값을 return Vector3.Distance(transform.position, _target.position); // 반환할거에요 -> 거리를 } }