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

如何利用OnVelocityChange事件监听rigidbody.velocity参数变化?

如何跟踪Rigidbody.velocity变化并触发操作

在Unity中,Rigidbody.velocity是物理引擎直接维护的字段,没有内置的变更回调事件,你可以通过以下两种常用方式实现跟踪:

1. 帧间对比检测(通用方案)

这是最可靠的方法,不管速度是由物理引擎(碰撞、重力)还是你的代码修改,都能检测到变化。核心思路是每帧记录上一帧的速度,然后与当前帧对比,差异超过精度阈值时触发操作。

代码示例:

using UnityEngine;

public class VelocityMonitor : MonoBehaviour
{
    private Rigidbody _rigidbody;
    private Vector3 _lastVelocity;
    // 浮点数精度阈值,避免因微小数值波动误触发
    [SerializeField] private float _threshold = 0.001f;

    void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
        // 初始化上一帧速度为当前值
        _lastVelocity = _rigidbody.velocity;
    }

    // 用FixedUpdate处理物理相关检测,与物理更新频率同步
    void FixedUpdate()
    {
        Vector3 currentVelocity = _rigidbody.velocity;
        
        // 对比当前速度与上一帧的差值
        if (Vector3.Distance(currentVelocity, _lastVelocity) > _threshold)
        {
            // 触发自定义操作
            HandleVelocityChange(currentVelocity, _lastVelocity);
            // 更新上一帧速度记录
            _lastVelocity = currentVelocity;
        }
    }

    // 自定义的速度变化处理逻辑
    private void HandleVelocityChange(Vector3 newVelocity, Vector3 oldVelocity)
    {
        // 这里写你需要执行的操作,比如日志、状态切换等
        Debug.Log($"Velocity changed: {oldVelocity} → {newVelocity}");
    }
}

注意点:

  • 使用FixedUpdate而非Update,因为物理引擎的更新是在FixedUpdate周期内,检测更准确。
  • 设置合理的_threshold,避免浮点数精度问题导致的频繁误触发。

2. 封装属性(代码可控场景)

如果你的项目中,velocity主要由自己的代码修改,而非物理引擎自动调整,可以封装一个自定义属性,在设置值时直接触发变更事件。

代码示例:

using UnityEngine;
using System;

public class ControlledVelocityTracker : MonoBehaviour
{
    private Rigidbody _rigidbody;
    [SerializeField] private float _threshold = 0.001f;
    
    // 定义速度变更事件,外部可以订阅
    public event Action<Vector3, Vector3> VelocityChanged;

    // 封装的Velocity属性
    public Vector3 Velocity
    {
        get => _rigidbody.velocity;
        set
        {
            if (Vector3.Distance(value, _rigidbody.velocity) > _threshold)
            {
                Vector3 oldVelocity = _rigidbody.velocity;
                _rigidbody.velocity = value;
                // 触发事件
                VelocityChanged?.Invoke(value, oldVelocity);
            }
        }
    }

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

    // 补充:如果需要捕获物理引擎自动修改的速度,仍需结合帧检测
    void FixedUpdate()
    {
        static Vector3 lastPhysicsVel = Vector3.zero;
        Vector3 currentVel = _rigidbody.velocity;
        if (Vector3.Distance(currentVel, lastPhysicsVel) > _threshold)
        {
            VelocityChanged?.Invoke(currentVel, lastPhysicsVel);
            lastPhysicsVel = currentVel;
        }
    }
}

适用场景:

  • 当你大部分时间通过Velocity属性设置速度时,能直接触发事件,无需每帧检测。
  • 若要覆盖物理引擎自动修改的情况,仍需保留FixedUpdate中的帧检测逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:45:16