Time Measurement in Unity


What would be a correct way to measure time and execute an event (i.e., publish or do a service call from Unity to ROS) if a specific time (i.e., 3.042 seconds) is reached? I would like the time elapsed to be relative to the system’s time, and not Unity’s “game time”.

I’ve read multiple Unity forum posts which have suggested using Coroutine with a “yield return WaitForSeconds” (scaled time) or “yield return new WaitForSecondsRealtime” (unscaled time), or using the Update and Time.deltaTime or FixedUpdate and Time.fixedDeltaTime (which is relative to Unity’s timescale and timestep used for physics and can cause issues to physics if changed), or InvokeRepeating, but the solutions either depend on Unity’s frame speed, are not precise enough, or have errors that increase over time.

The first problem is how to keep track of time, real “system time” and not Unity’s “game time”. The second problem is where to check if a specific time has been reached so that an event can be issued.

Would working with vSync or using the C# Timer Class (using System.Timers) be a more precise solution, or would this run into issues with threading?

Thank you.

I’d track system time by making a component that subscribes to the “/clock” topic. Every time a new clock message is received, record the time delta between Ros and Unity, i.e. message time minus Time.realTimeSinceStartup. And have a public accessor GetCurrentRosTime which returns that delta plus Time.realTimeSinceStartup.

As for waiting until a specific time has been reached: Yes, the C# Timer class is exactly how you would do this. RosConnection is designed to handle publishing a message from any thread, so that should be fine.

Having said that, how much timing precision do you really need/expect here? Publishing a message inherently takes a non-zero amount of time: it gets put into a queue to be processed by the ConnectionThread, which will get to it when it’s finished processing the rest of the queue (and if the queue is empty, the thread will sleep to avoid thrashing the processor). Once the thread gets to it, it gets sent via TCP-IP to the Ros-Tcp-Endpoint, then sent out again to the actual ROS subscribers.

Thanks for this information Laurie.

I will look more closely with the C# Timer class then and see if I can use some of the C# events, instead of using the Unity ones for this.

I'm looking for precision in terms of milliseconds, as I'm looking into both publishing to ROS but also to keep track of when other events occur in Unity to keep a log of tests results for tests I conduct.

For instance, in the pick-and-place demo, I could measure the time it took for the robot to move the manipulator over the block, the time it took to then grasp the block, the time it took for the block to then be placed in the target location, etc.

This would also be useful for when comparing algorithms, for instance if I implement autonomous navigation, which algorithm would cause the robot to reach the desired target faster (time would be one of the performance measures I would use to compare the different algorithms).

Ah, I see. In that case I suggest you measure the elapsed time locally and publish that value. There’s no point measuring the time it took for the log message to be received.

Yeah, that’s what I will try to do. Use the timer class locally on Unity to log the time in those cases.