• Hello
Search Results for

    Show / Hide Table of Contents

    Universal - Game Time - Monitor (Pro)

    In Unity, frame-based calculations rely heavily on UnityEngine.Time.deltaTime. Unfortunately, this time calculation is vulnerable to manipulation by cheat or hacking tools that allow unwanted acceleration, deceleration, or interruption of your game. AntiCheat has introduced a way to counteract such time manipulation.

    Monitor

    The 'GameTimeMonitor' (class GameTimeMonitor, namespace GUPS.AntiCheat.Monitor.Time) observes Unity's game time. It compares the reported frame delta time and physics (fixed) delta time against wall-clock UTC time to surface possible time-scale manipulation, such as SpeedHack-style tools. When it finds a deviation, it emits a GameTimeStatus to its observers.

    Status

    The monitor emits a GameTimeStatus, which implements IWatchedSubject:

    public struct GameTimeStatus : IWatchedSubject
    {
        // Deviation between Unity's frame delta time and wall-clock time.
        public ETimeDeviation DeltaDeviation { get; }
    
        // Deviation of the fixed (physics) delta time.
        public ETimeDeviation FixedDeltaDeviation { get; }
    }
    
    • DeltaDeviation: The deviation detected on Time.deltaTime (the per-frame time).
    • FixedDeltaDeviation: The deviation detected on Time.fixedDeltaTime (the physics step).

    Both use the ETimeDeviation enum:

    public enum ETimeDeviation : byte
    {
        None = 0,       // No deviation detected.
        Stopped = 1,    // Time has effectively stopped.
        SlowedDown = 2, // Time is running slower than expected.
        SpeedUp = 3     // Time is running faster than expected.
    }
    

    Lifecycle and timing

    The monitor collects samples in its OnUpdate callback (every frame). It keeps a rolling history of the most recent 25 Time.deltaTime samples and the matching UTC spans (scaled by Time.timeScale so a legitimately paused game is not reported as a slow-down). Only once the rolling history is full does it compare the means, build a GameTimeStatus, notify observers, and reset the history.

    Because of this windowed sampling, observers are notified periodically (about once every 25 frames) rather than on every single frame. To avoid spurious deviations, the history is reset when the monitor starts or resumes, and the UTC reference is reset on application focus and pause changes.

    A deviation is only reported once the difference between the mean game time and the mean real time exceeds the configured tolerance.

    Configuration

    The monitor exposes a single inspector field:

    • Tolerance: The allowed difference in milliseconds between game time and real time before a deviation is reported. Range 1 to 5000, default 10 (recommended 10-20). Because of game-dependent CPU or memory allocation spikes, a small tolerance avoids false positives.

    Supported platforms

    The monitor is available on all platforms.

    Requirements

    There are no requirements.

    How To Use

    Attach the 'GameTimeMonitor' to a child GameObject of the 'AntiCheat-Monitor' and pair it with the 'GameTimeCheatingDetector'.

    Add Monitor Component

    Add the 'GameTimeMonitor' MonoBehavior from the 'GUPS.AntiCheat.Monitor.Time' namespace to your 'AntiCheat-Monitor' GameObject, or better, to a child GameObject.

    Add the 'GameTimeMonitor' as a Component.

    Consume the status in code

    Besides pairing the monitor with a detector, you can subscribe your own observer to receive the GameTimeStatus directly. Every monitor derives from AMonitor and exposes Subscribe(IObserver<IWatchedSubject>), which returns an IDisposable you can dispose to unsubscribe.

    using System;
    using GUPS.AntiCheat.Core.Watch;
    using GUPS.AntiCheat.Monitor.Time;
    using UnityEngine;
    
    public class GameTimeStatusLogger : MonoBehaviour, IObserver<IWatchedSubject>
    {
        private void Start()
        {
            var monitor = GetComponentInChildren<GameTimeMonitor>();
            monitor.Subscribe(this);
        }
    
        public void OnNext(IWatchedSubject subject)
        {
            if (subject is GameTimeStatus status)
            {
                Debug.Log($"Delta: {status.DeltaDeviation}, FixedDelta: {status.FixedDeltaDeviation}");
            }
        }
    
        public void OnError(Exception error) { }
        public void OnCompleted() { }
    }
    

    Detect Game Time Tampering

    To react to the sent status and thus validate the calculated time deviations, you need a detector. To do this, use the 'GameTimeCheatingDetector', a detector designed to analyse the status sent by the 'GameTimeMonitor' and validate it for cheating.

    In This Article
    Back to top GuardingPearSoftware documentation