Hello everyone,
I’m currently working on a 2D platformer and managing player animations using a custom script. My problem is that the player’s animation gets stuck in the walking animation (WALK_ANIMATION
) even when the player is idle or stops moving.
Here’s the logic I’m using in my PlayerAnimationsManager
script (full code below):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAnimationsManager : MonoBehaviour
{
[Header("Important-References")]
private Animator PlayerAnimation;
private PlayerMovement playerMovementScriptsRef;
private SpriteRenderer PlayerSprite;
// Konstanten für Animationsnamen
private const string IDLE_ANIMATION = "NinjaPlayerIdle";
private const string WALK_ANIMATION = "NinjaWalkRight";
private const string NORMAL_ATTACK = "NinjaAttackRight";
private const float DashEffectDuration = 0.2f;
private static readonly Color DashColor = Color.red;
private string currentAnimationState = IDLE_ANIMATION; // Speichert den aktuellen Animationszustand
void Awake()
{
PlayerAnimation = GetComponent<Animator>();
playerMovementScriptsRef = FindObjectOfType<PlayerMovement>();
PlayerSprite = GetComponent<SpriteRenderer>();
}
void Update()
{
// Animationen und andere Aktionen verwalten
PlayerAnimationManager();
ChangeSpriteOnDash();
}
private void PlayerAnimationManager()
{
// Priorisiere Angriffsanimationen
if (AttackSystemPlayer.PlayerHeavyAttacked && Input.GetMouseButtonDown(0))
{
StartCoroutine(PlayFirstAttackAnimationAndWait());
return; // Andere Animationen ignorieren
}
// Blockiere andere Animationen, wenn der Angriff aktiv ist
if (PlayerAnimation.GetCurrentAnimatorStateInfo(0).IsName(NORMAL_ATTACK))
{
return;
}
// Spieler steht oder kann nicht laufen
if (playerMovementScriptsRef.moveDirectionX == 0 || !playerMovementScriptsRef.allowRunning)
{
ChangeAnimation(IDLE_ANIMATION);
return; // Verlasse die Methode, da der Spieler stillsteht
}
// Wenn beide Tasten gleichzeitig gedrückt werden, stoppe die Bewegung und gehe in Idle
if (Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.D))
{
ChangeAnimation(IDLE_ANIMATION);
playerMovementScriptsRef.moveDirectionX = 0; // Stoppe die Bewegung
return;
}
// Bewegung nach rechts
if (Input.GetKey(KeyCode.D) && playerMovementScriptsRef.allowRunning && playerMovementScriptsRef.moveDirectionX > 0)
{
ChangeAnimation(WALK_ANIMATION);
PlayerSprite.flipX = false; // Spiegelt den Spieler nach rechts
}
// Bewegung nach links
else if (Input.GetKey(KeyCode.A) && playerMovementScriptsRef.allowRunning && playerMovementScriptsRef.moveDirectionX < 0)
{
ChangeAnimation(WALK_ANIMATION);
PlayerSprite.flipX = true; // Spiegelt den Spieler nach links
}
}
private void ChangeSpriteOnDash()
{
if (Input.GetKeyDown(KeyCode.Space) && playerMovementScriptsRef.allowDashing)
{
PlayerSprite.color = DashColor;
Debug.Log("Der Spieler ist nicht mehr zu sehen!");
StartCoroutine(PlayerSpriteTrue());
}
}
private IEnumerator PlayFirstAttackAnimationAndWait()
{
// Starte die Angriffsanimation
ChangeAnimation(NORMAL_ATTACK);
Debug.Log("Der Spieler greift an");
// Warte, bis die Animation vollständig abgespielt ist
while (PlayerAnimation.GetCurrentAnimatorStateInfo(0).IsName(NORMAL_ATTACK) &&
PlayerAnimation.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
{
yield return null; // Warten auf den nächsten Frame
}
Debug.Log($"Animation {NORMAL_ATTACK} beendet.");
}
// Coroutine, die das Sprite nach einer kurzen Verzögerung wieder anzeigt
private IEnumerator PlayerSpriteTrue()
{
yield return new WaitForSeconds(DashEffectDuration);
PlayerSprite.color = Color.white;
}
private void ChangeAnimation(string animationName)
{
// Wechsel nur, wenn die Animation eine andere ist
if (currentAnimationState != animationName)
{
Debug.Log($"Wechsle Animation: {currentAnimationState} -> {animationName}");
PlayerAnimation.Play(animationName);
currentAnimationState = animationName;
}
}
}
- If the player is not moving (
moveDirectionX == 0
), I switch to the idle animation. - If the player moves left or right, the walking animation should play.
- I prioritize attack animations so they block other animations until they are completed.
The transitions seem fine, but when the player stops moving, the idle animation (IDLE_ANIMATION
) doesn’t consistently trigger. Instead, the player remains in the walking animation.
Here’s the full script for context:
Things I’ve checked:
- The animations in the Animator Controller are correctly named (
NinjaPlayerIdle
,NinjaWalkRight
, etc.). - Debugging shows that the
ChangeAnimation
function is being called with the correct animation names (IDLE_ANIMATION
when stopping, for example). PlayerMovement
is sending the correctmoveDirectionX
values, andallowRunning
works as expected.
What I suspect:
- It might be related to the Animator Controller or transitions overriding the
Play()
method. - Possibly, the
PlayerAnimation.GetCurrentAnimatorStateInfo(0)
is interfering when switching animations.
I’d appreciate any advice on what might be causing this or if there’s something I’m missing in my logic or Unity’s Animator behavior.
Thanks in advance for your help!