Unity3D动画状态机运行时敌方物体无法移动问题排查
问题背景
学习动画状态机实现过程中遇到运行异常:为敌方物体实现的逻辑为检测到玩家后自动向玩家移动,双方距离进入攻击范围时触发「攻击」状态。目前攻击触发可正常生效,但敌方物体完全无法执行跟随移动逻辑,没有任何位移,无法定位问题来自实现代码还是动画配置等其他环节,对应实现代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class enemyRun : StateMachineBehaviour { public float speed = 2.5f; public float attackRange = 3f; Transform player; Rigidbody rb; //Boss boss; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { player = GameObject.FindGameObjectWithTag("Player").transform; rb = animator.GetComponent<Rigidbody>(); //boss = animator.GetComponent<enemy>(); } // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { //boss.LookAtPlayer(); Vector3 target = new Vector3(player.position.x, player.position.y, player.position.z); Vector3 newPos = Vector3.MoveTowards(rb.position, target, speed * Time.fixedDeltaTime); rb.MovePosition(newPos); if (Vector3.Distance(player.position, rb.position) <= attackRange) { animator.SetTrigger("attack"); } } // OnStateExit is called when a transition ends and the state machine finishes evaluating this state override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { animator.ResetTrigger("attack"); } }
排查方向与修复方案
代码层面问题
- 时间参数调用错误:
OnStateUpdate和Update同频,是每帧调用的,这里移动计算用了Time.fixedDeltaTime(固定物理帧的时间步长,默认0.02s),当游戏实际帧率高于/低于50帧时,每帧移动的距离计算会完全错误,帧率较高时每帧移动距离极小,视觉上就是完全不动。把Time.fixedDeltaTime替换为Time.deltaTime即可。 - Rigidbody获取存在空引用风险:
animator.GetComponent<Rigidbody>()只会查找Animator组件所在物体上挂载的Rigidbody,如果你的Rigidbody挂在敌人对象的父节点或者子节点上,这里拿到的rb是null,后续移动逻辑自然不会生效。可以在OnStateEnter里加一行空判断快速定位:if (rb == null) Debug.LogError("未获取到Rigidbody,请检查组件挂载层级"); - 移动轴设置不合理:当前代码直接复制玩家的全坐标作为目标点,如果是地面3D游戏/2D游戏,玩家和敌人的Y轴坐标不一致,会导致敌人持续向Y轴方向移动,很容易被地形卡住表现为不动。地面单位的目标点应该锁定自身Y轴,修改为:
Vector3 target = new Vector3(player.position.x, rb.position.y, player.position.z);
配置层面问题
- Rigidbody约束设置错误:检查Rigidbody组件的Constraints选项,如果冻结了移动平面的对应轴(比如3D地面游戏冻结了X、Z轴位置,2D游戏冻结了X轴位置),所有代码控制的位移都会失效。地面单位通常只需要冻结Y轴位置、全旋转轴即可。
- 动画状态未正常切入:虽然攻击逻辑能触发,但要确认敌人是否真的进入了
enemyRun状态——如果状态机切换条件配置错误,敌人一直停留在Idle等其他状态,OnStateUpdate里的移动逻辑根本不会执行,可以在OnStateEnter里加Debug日志确认状态是否正常进入。 - Animator根运动冲突:如果Animator组件勾选了Apply Root Motion,动画自带的根运动位移会覆盖代码控制的Rigidbody移动。纯代码控制位移的话直接取消勾选该选项即可。
- 物理碰撞卡住:检查敌人的碰撞体尺寸是否合理,有没有初始就嵌入地形、其他静态碰撞体的情况,这种情况下Rigidbody的移动会被物理引擎阻挡,无法产生位移。
内容的提问来源于stack exchange,提问作者Teabelly
相关产品推荐
相关产品推荐

