Skip to main content

RTUpdater

Important Attention Reminder

Coding Style wiki


RTUpdater is a real-time update loop independent of MonoBehaviour (UniTask-driven), exposing onUpdate, onFixedUpdate, and onLateUpdate callbacks with a configurable targetFrameRate (loop frequency) and timeScale (own time scale). It is unaffected by Unity Time.timeScale (keeps running while the game is paused), and additionally supports StartOnThread() to switch the loop to the thread pool — suitable for network heartbeats, background polling, and similar scenarios.

NamespaceOxGKit.TimeSystem
Typepublic class RTUpdater
SourceRTUpdater.cs
using OxGKit.TimeSystem;

Quick Start

using OxGKit.TimeSystem;

var rtUpdater = new RTUpdater();

// Subscribe update callbacks
rtUpdater.onUpdate += (dt) => { /* per update (actual elapsed time) */ };
rtUpdater.onFixedUpdate += (fdt) => { /* fixed-interval update */ };
rtUpdater.onLateUpdate += (dt) => { /* late update */ };

// Configurable loop frequency and time scale
rtUpdater.targetFrameRate = 60f; // default 60
rtUpdater.timeScale = 1f; // 0 ~ 64, default 1

// Start the update loop (keeps running even while Time.timeScale = 0)
rtUpdater.Start();

// Always stop when the feature exits
rtUpdater.Stop();

General Rules

Loop Frequency and Time Scaling

  • Per cycle, the loop frequency = targetFrameRate × timeScale (Unity Time.timeScale is NOT multiplied in), and the wait interval is fixedDeltaTime = 1 / frequency.
  • Each cycle fires in order: onFixedUpdate(fixedDeltaTime)onUpdate(deltaTime)onLateUpdate(deltaTime), where deltaTime is the actual elapsed time of the previous cycle measured by the system clock, and fixedDeltaTime is the fixed interval value.

Attention The loop only runs while targetFrameRate is greater than 0 AND timeScale is greater than 0; if either is 0, the loop idles (no callbacks). For an update loop that follows Time.timeScale and game pause, use a DTUpdater instead (see Picking the Right Tool).

Lifecycle

Important The update loop is a UniTask loop — when the owner (feature/scene) exits, always call Stop, otherwise the loop keeps running; if a callback throws inside the loop, the updater stops automatically and rethrows.


Delegates

public delegate void RealTimeUpdate(float deltaTime);
public delegate void RealTimeFixedUpdate(float fixedDeltaTime);
public delegate void RealTimeLateUpdate(float deltaTime);

Members

MemberDescription
public RealTimeUpdate onUpdatePer-cycle update callback (parameter is the previous cycle's actual elapsed deltaTime).
public RealTimeFixedUpdate onFixedUpdatePer-cycle fixed-interval callback (parameter is fixedDeltaTime).
public RealTimeLateUpdate onLateUpdatePer-cycle late-update callback (fires after onUpdate).
public float timeSinceStartup { get; }Elapsed time since instance creation (seconds, system clock).
public float timeAtLastFrame { get; }Time point of the previous cycle (seconds).
public float timeScale { get; set; }Own time scale; assigned values are clamped to 0 ~ 64 (default 1).
public float targetFrameRate { get; set; }Target loop frequency (times per second); negative values are clamped to 0 (default 60).
public float deltaTime { get; }Actual elapsed time of the previous cycle (seconds).
public float fixedDeltaTime { get; }Current fixed interval (1 / frequency).

Constructors

public RTUpdater()

Creates the updater, using the system time at creation as the base for timeSinceStartup.


Methods

Method Overview

MethodDescription
StartStarts the update loop.
StartOnThreadStarts the update loop switched to the thread pool.
StopStops the update loop.
IsRunningWhether the loop is running.

Start

public void Start()

Starts the update loop (UniTask); calling it again while already running has no effect.

StartOnThread

public void StartOnThread()

Starts the update loop switched to the thread pool first (UniTask.SwitchToThreadPool); calling it again while already running has no effect.

Important Callbacks may run off the Unity main threaddo not access UnityEngine objects directly (marshal back to the main thread yourself).

Attention WebGL does not support multithreading — no switch happens on WebGL (behaves the same as Start).

Stop

public void Stop()

Stops the update loop and cancels the internal CancellationTokenSource; after stopping, Start can be called again to restart.

IsRunning

public bool IsRunning()

Returns whether the update loop is currently running.