using UnityEngine; [RequireComponent(typeof(Animator), typeof(SpriteRenderer))] public class PlayerAnimation : MonoBehaviour { [SerializeField] private Rigidbody2D body; [SerializeField] private PlayerDash dash; [SerializeField] private LayerMask groundLayers; [SerializeField] private bool artworkFacesRight = true; private Animator animator; private SpriteRenderer spriteRenderer; private static readonly int SpeedId = Animator.StringToHash("Speed"); private static readonly int StateId = Animator.StringToHash("State"); private readonly ContactPoint2D[] contacts = new ContactPoint2D[16]; private ContactFilter2D groundFilter; private void Awake() { animator = GetComponent(); spriteRenderer = GetComponent(); if (body == null || dash == null || groundLayers.value == 0) { Debug.LogError("PlayerAnimation: Body, Dash, Ground Layers를 연결하세요.", this); enabled = false; return; } groundFilter.SetLayerMask(groundLayers); groundFilter.useTriggers = false; } private void Update() { float horizontalSpeed = body.linearVelocity.x; animator.SetFloat(SpeedId, Mathf.Abs(horizontalSpeed)); bool grounded = false; int count = body.GetContacts(groundFilter, contacts); for (int i = 0; i < count; i++) { // A wall or ceiling does not count as support under the player. if (contacts[i].normal.y > 0.5f && body.linearVelocity.y <= 0.01f) { grounded = true; break; } } // Idle 0, Move 1, Jump 2, Fall 3, Dash 4. int state; if (dash.IsDashing) { state = 4; // Dash: 대시 중 } else if (grounded == false) { // 공중에서는 세로 속도로 상승과 낙하를 구분합니다. if (body.linearVelocity.y > 0.01f) { state = 2; // Jump: 위로 올라가는 중 } else { state = 3; // Fall: 정점에 도달했거나 내려오는 중 } } else { // 바닥에서는 가로 속도로 이동과 정지를 구분합니다. if (Mathf.Abs(horizontalSpeed) > 0.01f) { state = 1; // Move: 좌우로 이동 중 } else { state = 0; // Idle: 서 있는 중 } } animator.SetInteger(StateId, state); if (Mathf.Abs(horizontalSpeed) > 0.01f) { bool movingLeft = horizontalSpeed < 0f; if (artworkFacesRight) { spriteRenderer.flipX = movingLeft; } else { spriteRenderer.flipX = !movingLeft; } } } }