135 lines
4.2 KiB
C#
135 lines
4.2 KiB
C#
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<CharacterController>();
|
|
_animator = GetComponent<Animator>();
|
|
_traveler = GetComponent<TunnelTraveler>(); // 컴포넌트 캐싱
|
|
_inputActions = new PlayerInputActions();
|
|
|
|
_inputActions.Player.Jump.performed += ctx => OnJump();
|
|
_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<Vector2>();
|
|
move = new Vector3(_moveInput.x, 0, _moveInput.y).normalized;
|
|
_currentMoveDir = move;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isAttacking)
|
|
{
|
|
move = _currentMoveDir;
|
|
}
|
|
else
|
|
{
|
|
_moveInput = _inputActions.Player.Move.ReadValue<Vector2>();
|
|
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 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<IInteractable>();
|
|
if (interactable != null)
|
|
{
|
|
interactable.Interact(gameObject);
|
|
break; // 하나만 발견하면 중단
|
|
}
|
|
}
|
|
}
|
|
|
|
// 범위 확인용 기즈모
|
|
void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawWireSphere(transform.position, interactRange);
|
|
}
|
|
} |