using UnityEngine;
/// <summary>
/// GAME 1303 Tier 1 — Pushes movement state into the Animator so the Mechanim
/// controller (Idle / Walk / Run / Jump / Fall / Hurt / Dead) can drive itself.
///
/// SETUP
/// 1. Add to the same GameObject as PlayerController2D and an Animator.
/// 2. In your Animator Controller create these parameters:
/// Speed (Float) - absolute horizontal speed, 0 when standing
/// IsGrounded (Bool)
/// YVelocity (Float) - positive going up, negative falling
/// Jump (Trigger)
/// Hurt (Trigger)
/// Dead (Trigger)
/// 3. Transitions students typically wire:
/// Any -> Jump when Jump trigger
/// Idle -> Walk when Speed > 0.1 Walk -> Run when Speed > runThreshold
/// Walk -> Idle when Speed < 0.1
/// Any -> Fall when IsGrounded == false AND YVelocity < 0
/// Fall -> Idle when IsGrounded == true
///
/// If the Health script is on the object too, Hurt/Dead triggers fire automatically.
/// Works for non-player characters as well (e.g. Cozy Critters' pet) — just leave
/// the controller slot empty and call SetSpeed() from your own AI.
/// </summary>
[RequireComponent(typeof(Animator))]
public class PlayerAnimatorBridge : MonoBehaviour
{
[Tooltip("Optional. If empty, drive the animator manually with SetSpeed/SetGrounded.")]
public PlayerController2D controller;
[Tooltip("Optional. Hooks Hurt and Dead triggers.")]
public Health health;
// Cache hashes — faster than string lookups every frame
static readonly int SpeedHash = Animator.StringToHash("Speed");
static readonly int GroundedHash = Animator.StringToHash("IsGrounded");
static readonly int YVelHash = Animator.StringToHash("YVelocity");
static readonly int JumpHash = Animator.StringToHash("Jump");
static readonly int HurtHash = Animator.StringToHash("Hurt");
static readonly int DeadHash = Animator.StringToHash("Dead");
private Animator anim;
void Awake()
{
anim = GetComponent<Animator>();
if (controller == null) controller = GetComponent<PlayerController2D>();
if (health == null) health = GetComponent<Health>();
}
void OnEnable()
{
if (controller != null) controller.OnJumped.AddListener(TriggerJump);
if (health != null)
{
health.OnDamaged.AddListener(TriggerHurt);
health.OnDied.AddListener(TriggerDead);
}
}
void OnDisable()
{
if (controller != null) controller.OnJumped.RemoveListener(TriggerJump);
if (health != null)
{
health.OnDamaged.RemoveListener(TriggerHurt);
health.OnDied.RemoveListener(TriggerDead);
}
}
void Update()
{
if (controller == null) return;
anim.SetFloat(SpeedHash, Mathf.Abs(controller.Velocity.x));
anim.SetBool(GroundedHash, controller.IsGrounded);
anim.SetFloat(YVelHash, controller.Velocity.y);
}
// ---- Manual API for AI-driven characters ----
public void SetSpeed(float speed) => anim.SetFloat(SpeedHash, Mathf.Abs(speed));
public void SetGrounded(bool grounded) => anim.SetBool(GroundedHash, grounded);
public void TriggerJump() => anim.SetTrigger(JumpHash);
public void TriggerHurt() => anim.SetTrigger(HurtHash);
public void TriggerDead() => anim.SetTrigger(DeadHash);
}