캐릭터 움직임

This commit is contained in:
2026-09-24 00:30:35 +09:00
parent 3b323714fd
commit ac2828c0ed
75 changed files with 1680 additions and 72 deletions

View File

@@ -0,0 +1,72 @@
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Animator))]
public class PlayerController : MonoBehaviour,ISceneInitializable
{
// RedAnimController의 파라미터 이름과 정확히 일치해야 한다
private const string MoveXParam = "MoveX";
private const string MoveYParam = "MoveY";
private const string SpeedParam = "Speed";
[SerializeField] private float _moveSpeed = 4f;
private Rigidbody2D _rigidbody;
private Animator _animator;
private Vector2 _moveInput;
private void Awake()
{
_rigidbody = GetComponent<Rigidbody2D>();
_animator = GetComponent<Animator>();
}
public void OnSceneLoaded()
{
// 씬이 다시 로드돼도 중복 구독되지 않도록 먼저 떼고 붙인다
InputManager.Instance.OnMove_Event -= this.OnMove;
InputManager.Instance.OnMove_Event += this.OnMove;
}
private void OnDestroy()
{
if (InputManager.Instance != null)
{
InputManager.Instance.OnMove_Event -= this.OnMove;
}
}
// 입력 콜백은 값을 받아두기만 한다. 실제 이동은 물리 주기에 맞춰 FixedUpdate에서
private void OnMove(Vector2 moveInput)
{
// 대각선 입력이 (1,1)로 들어오면 더 빨라지므로 길이를 1로 제한
_moveInput = Vector2.ClampMagnitude(moveInput, 1f);
if (_moveInput.sqrMagnitude > 0.01f)
{
// 블렌드 트리는 스프라이트를 보간하지 못한다. 8방향 중 하나로 스냅해서 넣어야
// 한 클립에 가중치가 온전히 실려서 방향 경계에서 깜빡이지 않는다
Vector2 facing = SnapTo8(_moveInput);
_animator.SetFloat(MoveXParam, facing.x);
_animator.SetFloat(MoveYParam, facing.y);
}
// 입력이 0이면 MoveX/MoveY를 건드리지 않는다 -> 멈춰도 마지막으로 보던 방향을 유지
_animator.SetFloat(SpeedParam, _moveInput.magnitude);
}
private void FixedUpdate()
{
// Dynamic 바디지만 힘을 주지 않고 속도를 직접 대입하므로 관성 없이 딱딱 멈춘다
_rigidbody.linearVelocity = _moveInput * _moveSpeed;
}
// 입력 방향을 가장 가까운 45도 배수로 스냅한다 (대각선은 0.7071이 되어 블렌드 트리 좌표와 일치)
private static Vector2 SnapTo8(Vector2 direction)
{
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
float snapped = Mathf.Round(angle / 45f) * 45f * Mathf.Deg2Rad;
return new Vector2(Mathf.Cos(snapped), Mathf.Sin(snapped));
}
}