기본 애니메이션 및 컨트롤러 추가

kaykit 애셋 일부 적용
This commit is contained in:
2026-01-16 01:11:13 +09:00
parent 81929d5da9
commit 565f2e043b
15 changed files with 942 additions and 430 deletions

View File

@@ -5,23 +5,34 @@ public class PlayerMovement : MonoBehaviour
{
[Header("Movement Settings")]
public float moveSpeed = 5f;
public float jumpHeight = 1.5f; // 점프 높이
public float gravity = -19.62f; // 기본 중력보다 약간 무거운 값 추천
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 _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.Attack.performed += ctx => OnAttack();
_inputActions.Player.Interact.performed += ctx => OnInteract();
}
void OnEnable() => _inputActions.Enable();
@@ -29,46 +40,103 @@ public class PlayerMovement : MonoBehaviour
void Update()
{
// [해결책] 터널 이동 중이라면 일반 이동/중력 로직을 모두 중단합니다.
if (GetComponent<TunnelTraveler>().IsTraveling)
{
return;
}
// [중요] 터널 이동 중에는 모든 이동/중력 로직을 중단합니다.
if (_traveler != null && _traveler.IsTraveling) return;
// 1. 바닥 체크 (CharacterController의 기능 활용)
_isGrounded = _controller.isGrounded;
_animator.SetBool("isGrounded", _isGrounded);
bool isAttacking = _animator.GetCurrentAnimatorStateInfo(0).IsTag("Attack");
if (_isGrounded && _velocity.y < 0)
{
// 바닥에 닿아있을 때는 아주 작은 하방 힘만 유지 (안정성)
_velocity.y = -2f;
}
// 2. 이동 로직
_moveInput = _inputActions.Player.Move.ReadValue<Vector2>();
Vector3 move = transform.right * _moveInput.x + transform.forward * _moveInput.y;
_controller.Move(move * moveSpeed * Time.deltaTime);
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);
// 3. 중력 적용
_velocity.y += gravity * Time.deltaTime;
// 4. 최종 수직 이동 적용 (중력/점프 속도)
_controller.Move(_velocity * Time.deltaTime);
}
private void OnJump()
{
// TunnelTraveler가 이동 중인지 체크 (상태 변수 활용)
if (GetComponent<TunnelTraveler>().IsTraveling) return;
if (_traveler != null && _traveler.IsTraveling) return;
if (_isGrounded) _velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
if (_isGrounded)
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)
{
_velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
// 터널 노드(IInteractable)를 찾아 Interact 호출
IInteractable interactable = col.GetComponentInParent<IInteractable>();
if (interactable != null)
{
interactable.Interact(gameObject);
break; // 하나만 발견하면 중단
}
}
}
// 터널 이동 등 외부에서 중력을 초기화해야 할 때 사용
public void ResetVelocity()
// 범위 확인용 기즈모
void OnDrawGizmosSelected()
{
_velocity.y = 0;
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, interactRange);
}
}