using UnityEngine; using UnityEngine.InputSystem; public class PlayerMovement : MonoBehaviour { [Header("Movement Settings")] public float moveSpeed = 5f; public float rotationSpeed = 10f; public float jumpHeight = 1.5f; public float gravity = -19.62f; [Header("Interaction Settings")] [SerializeField] private float interactRange = 3f; [SerializeField] private LayerMask interactableLayer; // 터널 노드 레이어 private CharacterController _controller; private PlayerInputActions _inputActions; private Animator _animator; private TunnelTraveler _traveler; // 터널 이동 컴포넌트 참조 private Vector2 _moveInput; private Vector3 _velocity; private Vector3 _currentMoveDir; private bool _isGrounded; void Awake() { _controller = GetComponent(); _animator = GetComponent(); _traveler = GetComponent(); // 컴포넌트 캐싱 _inputActions = new PlayerInputActions(); _inputActions.Player.Jump.performed += ctx => OnJump(); _inputActions.Player.Attack.performed += ctx => OnAttack(); _inputActions.Player.Interact.performed += ctx => OnInteract(); } void OnEnable() => _inputActions.Enable(); void OnDisable() => _inputActions.Disable(); void Update() { // [중요] 터널 이동 중에는 모든 이동/중력 로직을 중단합니다. if (_traveler != null && _traveler.IsTraveling) return; _isGrounded = _controller.isGrounded; _animator.SetBool("isGrounded", _isGrounded); bool isAttacking = _animator.GetCurrentAnimatorStateInfo(0).IsTag("Attack"); if (_isGrounded && _velocity.y < 0) { _velocity.y = -2f; } Vector3 move = Vector3.zero; if (_isGrounded) { if (isAttacking) { move = Vector3.zero; _currentMoveDir = Vector3.zero; } else { _moveInput = _inputActions.Player.Move.ReadValue(); move = new Vector3(_moveInput.x, 0, _moveInput.y).normalized; _currentMoveDir = move; } } else { if (isAttacking) { move = _currentMoveDir; } else { _moveInput = _inputActions.Player.Move.ReadValue(); move = new Vector3(_moveInput.x, 0, _moveInput.y).normalized; if (move.magnitude > 0.1f) _currentMoveDir = move; } } if (move.magnitude >= 0.1f) { Quaternion targetRotation = Quaternion.LookRotation(move); if (!isAttacking) transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); _controller.Move(move * moveSpeed * Time.deltaTime); } _animator.SetFloat("MoveSpeed", isAttacking && _isGrounded ? 0 : move.magnitude); _velocity.y += gravity * Time.deltaTime; _controller.Move(_velocity * Time.deltaTime); } private void OnJump() { if (_traveler != null && _traveler.IsTraveling) return; if (_isGrounded) _velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); } private void OnAttack() { if (_traveler != null && _traveler.IsTraveling) return; _animator.SetTrigger("Attack"); } private void OnInteract() { // 터널 이동 중에는 상호작용 금지 if (_traveler != null && _traveler.IsTraveling) return; // 상호작용 애니메이션 실행 _animator.SetTrigger("Interact"); // [핵심 추가] 주변 상호작용 대상(터널 노드 등) 검색 Collider[] colliders = Physics.OverlapSphere(transform.position, interactRange, interactableLayer); foreach (var col in colliders) { // 터널 노드(IInteractable)를 찾아 Interact 호출 IInteractable interactable = col.GetComponentInParent(); if (interactable != null) { interactable.Interact(gameObject); break; // 하나만 발견하면 중단 } } } // 범위 확인용 기즈모 void OnDrawGizmosSelected() { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, interactRange); } }