Vector3.MoveTowards失效:受动画影响无法让野猪追逐玩家
解决办法
问题出在Animator的根运动(Root Motion)——当根运动启用时,动画会直接修改角色的Transform位置,你用Vector3.MoveTowards修改的位置会被动画帧覆盖,所以看起来没效果。以下是几种可行的解决思路:
1. 动态开关根运动
在切换到追逐状态(Idle动画)时关闭根运动,让代码完全控制角色位置;回到巡逻状态时再重新开启,让动画控制巡逻移动:
private Animator _animator; private bool _canChase; private void Awake() { _animator = GetComponent<Animator>(); } // 触发追逐的方法(比如检测到玩家时调用) public void StartChasing() { _canChase = true; _animator.Play("Idle"); // 切换到Idle动画 _animator.applyRootMotion = false; // 关闭根运动,让代码接管位置 } // 结束追逐的方法 public void StopChasing() { _canChase = false; _animator.Play("Patrol"); // 切回巡逻动画 _animator.applyRootMotion = true; // 重新开启根运动 } private void Update() { if (_canChase) { MoveTowardsPlayer(); } } private void MoveTowardsPlayer() { var step = speed * Time.deltaTime; transform.position = Vector3.MoveTowards(transform.position, prey.position, step); }
2. 用动画层权重分离动画控制
如果需要保留Idle动画的细节(比如呼吸、头部动作),可以把巡逻和Idle动画放在不同的动画层,通过调整权重来切换,同时只让巡逻层启用根运动:
- 在Animator窗口创建两个层:
PatrolLayer(放巡逻动画)和IdleLayer(放Idle动画) - 设置
PatrolLayer的Root Motion为启用,IdleLayer关闭根运动 - 用代码切换层权重:
public void StartChasing() { _canChase = true; // 提升Idle层权重,降低巡逻层权重 _animator.SetLayerWeight(_animator.GetLayerIndex("IdleLayer"), 1f); _animator.SetLayerWeight(_animator.GetLayerIndex("PatrolLayer"), 0f); } public void StopChasing() { _canChase = false; _animator.SetLayerWeight(_animator.GetLayerIndex("IdleLayer"), 0f); _animator.SetLayerWeight(_animator.GetLayerIndex("PatrolLayer"), 1f); }
3. 修改Idle动画的根运动导入设置
直接修改Idle动画的导入参数,让它不影响角色的X轴位置:
- 在Project窗口选中Idle动画文件
- 在Inspector窗口的Animation Import Settings里,找到Root Motion部分
- 把
Root Transform Position (XZ)设置为Baked into Pose,这样动画不会修改角色的XZ平面位置,只保留必要的根运动(比如Y轴或旋转) - 保存设置后,即使开着根运动,代码修改X轴位置也不会被动画覆盖
内容的提问来源于stack exchange,提问作者kakubei
相关产品推荐
相关产品推荐

