Unity跳跃动画冻结问题求助:按下空格键后动画无法正常过渡
跳跃动画冻结,状态过渡失效问题排查与解决
问题描述
作为Unity新手,遇到跳跃动画异常:按下空格键后动画正常播放,但随后冻结,Animator窗口可见状态过渡未生效,已排查数日无果。
相关代码
PlayerMovement脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController2D controller; public Animator animator; public float runSpeed = 40f; float horizontalMove = 0f; bool jump = false; void Update() { // Get horizontal input and set speed horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed; animator.SetFloat("Speed", Mathf.Abs(horizontalMove)); // Check for jump input if (Input.GetButtonDown("Jump")) { jump = true; animator.SetBool("IsJumping", true); Debug.Log("Jump button pressed. IsJumping set to true."); } // Debug animator's current state and parameter values Debug.Log($"Current Animator State: {animator.GetCurrentAnimatorStateInfo(0).IsName("Player_Idle")}"); Debug.Log($"IsJumping: {animator.GetBool("IsJumping")}"); } public void OnLanding() { // Called when the player lands animator.SetBool("IsJumping", false); Debug.Log("Player landed. IsJumping set to false."); } void FixedUpdate() { // Move the character and reset the jump flag controller.Move(horizontalMove * Time.fixedDeltaTime, false, jump); jump = false; // Debug movement and jumping values Debug.Log($"HorizontalMove: {horizontalMove}, Jump: {jump}"); } }
CharacterController2D脚本
using UnityEngine; using UnityEngine.Events; public class CharacterController2D : MonoBehaviour { [SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps. [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100% [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement [SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping; [SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character [SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded. [SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings [SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded private bool m_Grounded; // Whether or not the player is grounded. const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up private Rigidbody2D m_Rigidbody2D; private bool m_FacingRight = true; // For determining which way the player is currently facing. private Vector3 m_Velocity = Vector3.zero; [Header("Events")] [Space] public UnityEvent OnLandEvent; [System.Serializable] public class BoolEvent : UnityEvent<bool> { } public BoolEvent OnCrouchEvent; private bool m_wasCrouching = false; private void Awake() { m_Rigidbody2D = GetComponent<Rigidbody2D>(); if (OnLandEvent == null) OnLandEvent = new UnityEvent(); if (OnCrouchEvent == null) OnCrouchEvent = new BoolEvent(); } private void FixedUpdate() { bool wasGrounded = m_Grounded; m_Grounded = false; // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground // This can be done using layers instead but Sample Assets will not overwrite your project settings. Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround); for (int i = 0; i < colliders.Length; i++) { if (colliders[i].gameObject != gameObject) { m_Grounded = true; if (!wasGrounded) OnLandEvent.Invoke(); } } } }
已进行的排查操作
- 过渡未设置Exit Time
- 过渡时长设为0秒
- 配置Any State到跳跃状态的过渡(条件为IsJumping=true),跳跃状态到Idle/Run状态的过渡(条件为IsJumping=false且Speed参数正常,Speed功能正常)
- 绑定OnLandEvent时只能从MonoScript中选择字符串名称的函数,不确定是否相关
解决方案
1. 确认OnLandEvent绑定有效性
检查CharacterController2D组件的OnLandEvent是否正确关联到PlayerMovement的OnLanding方法:
- 如果使用字符串绑定,确保函数名拼写完全一致(区分大小写);
- 优先采用拖拽绑定:在Inspector中找到CharacterController2D的OnLandEvent,点击"+"号,拖拽Player对象到对象框,然后从下拉菜单中选择
PlayerMovement -> OnLanding(); - 运行时查看Debug日志,若未出现"Player landed. IsJumping set to false.",说明事件未触发,需检查GroundCheck位置是否在玩家脚底、m_WhatIsGround是否包含地面图层。
2. 简化动画过渡条件
- 跳跃状态到Idle/Run的过渡,暂时去掉Speed条件,只保留
IsJumping=false,测试是否能正常过渡; - 确认Animator参数中的IsJumping为Bool类型,未被误设为其他类型;
- 检查跳跃动画的Loop Time是否未勾选,避免动画循环导致无法触发过渡。
3. 代码细节修正
- 修正PlayerMovement脚本开头的笔误
eusing为using,避免编译错误; - 验证CharacterController2D中GroundCheck的检测逻辑:确保OverlapCircleAll能正确检测到地面,可在Scene窗口查看GroundCheck的位置和检测范围。
4. 实时调试验证
运行游戏时,在Animator窗口的Parameters面板观察IsJumping的值:
- 若落地后IsJumping仍为true,说明OnLanding未被调用,回到第一步排查绑定问题;
- 若IsJumping已变为false但过渡仍未触发,检查过渡的Has Exit Time是否被意外勾选,或过渡的条件逻辑是否冲突。
内容的提问来源于stack exchange,提问作者Tom Hunt
相关产品推荐
相关产品推荐

