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

如何实现Unity游戏时间与Unix纪元时间的映射同步?

Unity与ROS2物理仿真的时间戳同步可靠方案

问题核心

Unity的FixedUpdate物理时间与Unix纪元时间无直接关联,ROS2规划软件要求传感器数据和执行器动作必须携带Unix时间戳:

  • 用DateTimeOffset.UtcNow打戳:Unity卡顿批量执行FixedUpdate时,同一物理帧的传感器数据会被打上不同墙钟时间,导致接收端速度计算异常
  • 用Time.fixedTimeAsDouble:无法关联至Unix时间,无法满足ROS2的时间戳要求
  • 启动时同步墙钟与游戏时间:受Unity启动加载耗时影响,会产生秒级误差,精度不足

可靠映射方案:动态校准时间偏移量

通过周期性校准物理时间与Unix时间的偏移量,确保FixedUpdate内的时间戳完全一致,同时消除启动误差和运行时漂移。

实现步骤

  • 维护两个全局变量:
    • _unixTimeOffset:存储Unix纪元时间与Unity物理启动时间的偏移量(公式:Unix时间 = Time.fixedTimeAsDouble + _unixTimeOffset)
    • _lastCalibrationFrame:记录上次校准的物理帧计数,控制校准频率
  • 在FixedUpdate中定期校准:每隔N个物理帧(如100帧≈2秒),重新计算偏移量;非校准帧直接用物理时间加偏移量生成时间戳
  • 处理暂停/恢复:应用暂停恢复时重新校准,避免暂停期间偏移失效

代码示例

using UnityEngine;
using System;

public class RosTimeSync : MonoBehaviour
{
    [SerializeField] private int calibrationInterval = 100; // 校准间隔(物理帧数,默认2秒@50Hz)
    private double _unixTimeOffset;
    private int _lastCalibrationFrame;

    void Start()
    {
        CalibrateTimeOffset();
    }

    void FixedUpdate()
    {
        // 定期校准偏移量
        if (Time.frameCount - _lastCalibrationFrame >= calibrationInterval)
        {
            CalibrateTimeOffset();
            _lastCalibrationFrame = Time.frameCount;
        }

        // 生成当前物理帧对应的Unix毫秒级时间戳(符合ROS2标准)
        double unixTimestampMs = (Time.fixedTimeAsDouble + _unixTimeOffset) * 1000;
        // 替换为实际ROS2传感器数据发布逻辑
        PublishSensorData(unixTimestampMs);
    }

    void OnApplicationPause(bool pauseStatus)
    {
        if (!pauseStatus)
        {
            CalibrateTimeOffset();
            _lastCalibrationFrame = Time.frameCount;
        }
    }

    private void CalibrateTimeOffset()
    {
        // 获取当前高精度Unix时间(秒级,含毫秒小数)
        double currentUnixTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + DateTimeOffset.UtcNow.Millisecond / 1000.0;
        // 计算偏移量:Unix时间 - Unity物理启动时间
        _unixTimeOffset = currentUnixTime - Time.fixedTimeAsDouble;
    }

    private void PublishSensorData(double timestampMs)
    {
        // 示例:打印时间戳,实际替换为ROS2话题发布
        Debug.Log($"Sensor timestamp (ms): {timestampMs:F3}");
    }
}

关键说明

  • 校准频率:可根据精度需求调整,过高会增加性能开销,过低会积累漂移误差,建议1-5秒校准一次
  • 执行器同步:ROS2订阅到带Unix时间戳的指令后,可通过(Unix时间 - _unixTimeOffset)反算出对应的Unity物理时间,在匹配的FixedUpdate帧执行动作,避免延迟导致的时机偏差
  • 误差控制:单次校准误差在毫秒级,周期性校准会抵消Unity运行时的时间漂移,远优于启动时一次性同步的方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:02:25