You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity跑酷游戏动画切换循环异常及角色移动问题求助

跑酷游戏角色跑停异常与动画切换问题

我制作了一款跑酷游戏,设定为按住鼠标左键时角色奔跑,松开则停止。但实际运行时,按住鼠标左键期间,角色会出现跑-停-反复奔跑的异常,Run动画与Idle动画也会不断切换。

角色移动代码

using UnityEngine;

public class StickmanMover : MonoBehaviour
{
[SerializeField] private float _maxSpeed;
[SerializeField] private float _speed;

private Rigidbody _rigidbody;

private void Start()
{
    _rigidbody = GetComponent<Rigidbody>();
}

private void Update()
{
    if (Input.GetKey(KeyCode.Mouse0) && _rigidbody.velocity.magnitude < _maxSpeed)
    {
        _rigidbody.AddForce(Vector3.forward * _speed * Time.deltaTime);
    }
}
}

动画控制代码

using UnityEngine;

public class StickmanAnimator : MonoBehaviour
{
private Animator _animator;

private void Start()
{
    _animator = GetComponent<Animator>();
}

private void Update()
{
    if (Input.GetKey(KeyCode.Mouse0))
    {
        _animator.SetTrigger("Run");
    }
    else
    {
        _animator.SetTrigger("Idle");
    }
}
}

动画过渡设置截图

动画过渡设置1
动画过渡设置2


问题根源

  1. 动画控制逻辑错误:SetTrigger会在每帧调用时触发一次,且Trigger参数会自动重置。按住鼠标时,每帧都触发Run Trigger,加上动画过渡的条件设置,会导致动画在Run和Idle之间反复切换。
  2. 移动逻辑的边界波动:当角色速度接近_maxSpeed时,_rigidbody.velocity.magnitude < _maxSpeed会频繁在true和false之间切换,导致AddForce时断时续,角色速度不稳定,视觉上呈现跑停交替。

修复方案

1. 替换动画触发方式(核心修复)

将SetTrigger改为SetBool,因为Bool参数可以持续保持状态,不会每帧触发切换:
修改后的动画控制代码:

using UnityEngine;

public class StickmanAnimator : MonoBehaviour
{
private Animator _animator;
// 使用StringToHash避免字符串查找开销
private static readonly int IsRunning = Animator.StringToHash("IsRunning");

private void Start()
{
    _animator = GetComponent<Animator>();
}

private void Update()
{
    bool isMouseHeld = Input.GetKey(KeyCode.Mouse0);
    _animator.SetBool(IsRunning, isMouseHeld);
}
}

同时在Animator控制器中做以下调整:

  • 删除原有的Run和Idle Trigger参数,添加一个Bool类型的IsRunning参数
  • 设置Idle到Run的过渡条件:IsRunning == true
  • 设置Run到Idle的过渡条件:IsRunning == false
  • 可适当调整过渡的Exit Time和Fixed Duration,避免过渡过于突兀

2. 优化移动逻辑

解决速度接近_maxSpeed时的加力波动问题,推荐两种方式:

方式一:使用目标速度加速度控制(更平滑)
using UnityEngine;

public class StickmanMover : MonoBehaviour
{
[SerializeField] private float _maxSpeed;
[SerializeField] private float _acceleration; // 加速度,控制加速快慢

private Rigidbody _rigidbody;

private void Start()
{
    _rigidbody = GetComponent<Rigidbody>();
}

// 物理逻辑建议放在FixedUpdate,与物理帧同步
private void FixedUpdate()
{
    if (Input.GetKey(KeyCode.Mouse0))
    {
        _rigidbody.drag = 0; // 奔跑时关闭拖拽
        Vector3 targetVelocity = Vector3.forward * _maxSpeed;
        // 计算需要的力来趋近目标速度
        Vector3 force = (targetVelocity - _rigidbody.velocity) * _acceleration;
        _rigidbody.AddForce(force, ForceMode.Acceleration);
    }
    else
    {
        _rigidbody.drag = 5f; // 松开鼠标时增加拖拽减速
    }
}
}
方式二:给速度判断加阈值(简单修改)
private void Update()
{
    // 增加0.1的阈值,避免速度在_maxSpeed附近波动时频繁开关加力
    if (Input.GetKey(KeyCode.Mouse0) && _rigidbody.velocity.magnitude < _maxSpeed - 0.1f)
    {
        _rigidbody.AddForce(Vector3.forward * _speed * Time.deltaTime);
    }
}

内容的提问来源于stack exchange,提问作者user21403547

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:44:59