Unity中使用bool判断玩家跳跃状态触发动画失败问题求助
问题分析与解决方案
嗨,作为编程新手能写出这样的代码已经很棒啦!咱们一步步来找出问题所在,然后逐个解决:
核心问题1:isJumping变量没有实时同步
你的CharacterAnimation脚本里声明了一个本地的isJumping变量,而且只在Start()方法里获取了一次Character2dController中的值,之后就再也没有更新过。更关键的是,你在Start()里还手动把它设为false,直接覆盖了初始值,导致动画脚本永远拿不到控制器里的最新状态。
核心问题2:Character2dController里的isJumping被错误重置
在Update()方法的最后,你写了isJumping = false;,而Jump()方法是在Update()一开始调用的——这就导致了一个矛盾:
- 当你按下跳跃键,
Jump()把isJumping设为true - 但紧接着
Update()的最后一行又把它改回false
这个变量刚变成true就被重置,动画脚本根本抓不到它为true的瞬间。
次要问题:IsGrounded方法存在空引用风险
当Physics2D.OverlapCircle没有检测到地面时,groundCheck会是null,这时候你访问groundCheck.gameObject会直接触发空引用错误,导致代码中断。
修复步骤
步骤1:让动画脚本实时获取控制器的isJumping状态
删掉CharacterAnimation里的本地isJumping变量,改成直接持有控制器的引用,在Update()里实时读取它的状态:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterAnimation : MonoBehaviour { private Animator anim; // 直接持有控制器的引用,不要本地变量 private Character2dController controller; private Rigidbody2D rb; void Start() { anim = GetComponent<Animator>(); // 获取控制器组件并保存引用 controller = GetComponent<Character2dController>(); rb = GetComponent<Rigidbody2D>(); } void Update() { // 行走动画逻辑保持不变 if (Input.GetKey("a") || Input.GetKey("d")) { anim.SetBool("isWalking", true); } else { anim.SetBool("isWalking", false); } // 翻转逻辑保持不变 if (Input.GetKey("a")) { transform.localScale = new Vector3(-1, 1, 1); } if (Input.GetKey("d")) { transform.localScale = new Vector3(1, 1, 1); } // 实时读取控制器里的isJumping状态 if(controller.isJumping) { anim.SetTrigger("Up"); // 触发后重置控制器的isJumping,避免重复触发动画 controller.isJumping = false; } } }
步骤2:修正Character2dController里的isJumping重置逻辑
把Update()里的isJumping = false;删掉,改成由动画脚本触发后重置(上面的代码已经实现)。同时优化IsGrounded方法避免空引用:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Character2dController : MonoBehaviour { public float MovementSpeed = 8; public float JumpForce = 5; public Transform feet; public bool isJumping; private Rigidbody2D rb; public LayerMask groundLayers; void Start() { rb = GetComponent<Rigidbody2D>(); isJumping = false; } void Update() { Jump(); var movement = Input.GetAxis("Horizontal"); transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed; // 删掉这行错误的重置代码! // isJumping = false; } void Jump() { if (Input.GetButtonDown("Jump") && IsGrounded()) { isJumping = true; rb.AddForce(new Vector2(0, JumpForce), ForceMode2D.Impulse); } } public bool IsGrounded() { // 先判断groundCheck是否不为null,再返回结果 Collider2D groundCheck = Physics2D.OverlapCircle(feet.position, 0.5f, groundLayers); return groundCheck != null; } }
进阶优化:用刚体速度判断跳跃状态
其实还有更可靠的方式判断跳跃——直接读取Rigidbody2D的Y轴速度,这样不需要依赖isJumping变量,彻底避免同步问题:
在CharacterAnimation的Update()里替换跳跃判断逻辑:
// 替换原来的isJumping判断 if(rb.velocity.y > 0.1f && !controller.IsGrounded()) { anim.SetTrigger("Up"); } // 还可以添加下落动画的判断 if(rb.velocity.y < -0.1f && !controller.IsGrounded()) { anim.SetTrigger("Down"); }
内容的提问来源于stack exchange,提问作者Nautixx
相关产品推荐
相关产品推荐

