• Hello
Search Results for

    Show / Hide Table of Contents

    Universal - Game Time - Detector (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.

    Detector

    The 'GameTimeCheatingDetector' (class GameTimeCheatingDetector, namespace GUPS.AntiCheat.Detector) detects manipulation of Unity's game time (UnityEngine.Time.deltaTime and fixedDeltaTime), commonly caused by SpeedHack-style tools. It subscribes to the 'GameTimeMonitor' and evaluates the reported time deviations. In addition, once cheating is detected it starts a countermeasure: it calculates the game time from system ticks so that the value stays correct even while Time is being manipulated, and exposes it through GUPS.AntiCheat.Protected.Time.ProtectedTime.

    Observed subject

    The detector subscribes in Awake to the GameTimeStatus published by the 'GameTimeMonitor' that sits on the same GameObject. If no monitor is present on the same GameObject, the detector logs a warning and stays idle.

    Status

    The detector notifies its observers with a CheatingDetectionStatus, which implements IDetectorStatus:

    public struct CheatingDetectionStatus : IDetectorStatus
    {
        // Probability that the detection is a false positive, in the range [0.0, 1.0].
        public float PossibilityOfFalsePositive { get; }
    
        // The threat rating reported with this detection.
        public uint ThreatRating { get; }
    }
    

    Threat rating and false positives

    • PossibilityOfFalsePositive: 0.45 (fixed). It is intentionally high because the game time monitor is sensitive to legitimate CPU or GC spikes.
    • ThreatRating: default 25 (inspector field, recommended 25). It is kept low because false positives are likely and many small detections may be sent to the AntiCheat-Monitor.

    Lifecycle and timing

    • Subscribes to the monitor in Awake and resets its time state.
    • Refreshes its internal time every frame in Update; resets the UTC reference on OnApplicationFocus / OnApplicationPause, and resets the level time on scene load.
    • Delta-time detection is windowed: it feeds each DeltaDeviation into a rolling window of 25 samples and reports cheating once at least half of the window shows the same non-None deviation.
    • After cheating is detected the detector is one-shot: it stops processing further monitor notifications and switches ProtectedTime to the system-tick fallback.

    Configuration

    • Is Active (isActive, bool, default true) - whether the detector is active and watching.
    • Threat Rating (threatRating, uint, default 25) - the threat rating reported on each detection.
    • Detect Delta Time Cheating (DetectDeltaTimeCheating, bool, default true) - react to deltaTime manipulation, commonly used to speed up or slow down the game.
    • Detect Fixed Delta Time Cheating (DetectFixedDeltaTimeCheating, bool, default false) - react to fixedDeltaTime manipulation, often used to skip physics updates (e.g. to walk through walls). When enabled, you must use the ProtectedTime.fixedDeltaTime setter to update the fixed delta time.
    • On Cheating Detection Event (OnCheatingDetectionEvent) - a UnityEvent raised on every detection; wire up reactions in the inspector without writing an observer.

    Supported platforms

    The detector is available on all platforms.

    Requirements

    There are no requirements. A 'GameTimeMonitor' must be present on the same GameObject.

    How To Use

    Attach a 'GameTimeMonitor' (if not already done) and the 'GameTimeCheatingDetector' to a child GameObject of the 'AntiCheat-Monitor', then define a reaction to detected cheating.

    Add Monitor Component

    To detect game time manipulation, a source of game time deviation data is required. Add the 'GameTimeMonitor' to the same GameObject you attach the 'GameTimeCheatingDetector' to. The detector subscribes to the 'GameTimeStatus' sent by the monitor.

    Add Detector Component

    Manual

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

    Add the 'GameTimeCheatingDetector' as a Component.

    Prefab

    There is also a prefab, including the detector and the monitor, which you can directly attach as a GameObject to the 'AntiCheat-Monitor'.

    Add the 'Game Time Cheating Detector' prefab to the 'AntiCheat-Monitor'.

    Settings

    After attaching the 'GameTimeCheatingDetector' MonoBehavior to a GameObject, you will see the following in the inspector:

    The settings of the 'GameTimeCheatingDetector' Component.

    • General Settings: Define here whether the detector should be active.
    • Threat Rating Settings: Define here the severity of the detected cheating.
    • Detection Settings: Choose whether to react to delta time and/or fixed delta time cheating.
    • Observable Settings: Add here callbacks invoked when cheating is detected.

    Runtime

    Once cheating is detected, the detector provides a trustworthy game time derived from system ticks, exposed by the ProtectedTime class. Replace your usage of UnityEngine.Time with GUPS.AntiCheat.Protected.Time.ProtectedTime:

    // Replace your usage of the UnityEngine.Time class with GUPS.AntiCheat.Protected.Time.ProtectedTime.
    public static class ProtectedTime
    {
        // The time in seconds it took to complete the last frame (Read Only).
        public static float deltaTime { get; }
    
        // The real time in seconds since the game started (Read Only).
        public static float realtimeSinceStartup { get; }
    
        // The time at the beginning of this frame (Read Only). This is the time in seconds since the start of the game.
        public static float time { get; }
    
        // The scale at which the time is passing. This can be used for slow motion effects.
        public static float timeScale { get; set; }
    
        // The time this frame has started (Read Only). This is the time in seconds since the last level has been loaded.
        public static float timeSinceLevelLoad { get; }
    
        // The timeScale-independent interval in seconds from the last frame to the current one (Read Only).
        public static float unscaledDeltaTime { get; }
    
        // The timeScale-independent time for this frame (Read Only). This is the time in seconds since the start of the game.
        public static float unscaledTime { get; }
    }
    

    Consume the detection in code

    Besides the inspector event, you can subscribe your own observer. Every detector derives from ADetector and exposes Subscribe(IObserver<IDetectorStatus>), which returns an IDisposable you can dispose to unsubscribe. Get the detector via the AntiCheat-Monitor:

    using System;
    using GUPS.AntiCheat;
    using GUPS.AntiCheat.Core.Detector;
    using GUPS.AntiCheat.Detector;
    using UnityEngine;
    
    public class GameTimeDetectionLogger : MonoBehaviour, IObserver<IDetectorStatus>
    {
        private void Start()
        {
            var detector = AntiCheatMonitor.Instance.GetDetector<GameTimeCheatingDetector>();
            detector.Subscribe(this);
        }
    
        public void OnNext(IDetectorStatus status)
        {
            Debug.LogWarning($"Game time cheating detected (threat={status.ThreatRating}, fp={status.PossibilityOfFalsePositive}).");
        }
    
        public void OnError(Exception error) { }
        public void OnCompleted() { }
    }
    

    React On Cheating

    When the monitor (data provider) and detector (data validator) are set up, you surely want to react to detected cheating.

    Punisher

    In general, any cheat detected is forwarded to the 'AntiCheat-Monitor', which calculates an overall threat level. Based on the threat level, you can apply punishments by using Punisher components added to a child GameObject of the 'AntiCheat-Monitor'. There are some built-in punishers that you can find here as prefabs:

    The location of the built-in Punisher prefabs.

    Inspector

    You can set a callback in the Unity Inspector view of the detector. This callback is invoked as soon as the specific cheating is detected.

    A list of callbacks invoked when cheating is detected by the detector.

    Code

    If you would like to write a custom listener for the detector, you can attach an observer:

    // Get the detector.
    var detector = AntiCheatMonitor.Instance
          .GetDetector<GameTimeCheatingDetector>();
    
    // Subscribe as observer and get notified on inconsistency.
    detector.Subscribe(myObserver);
    

    The detector also has an inherited property 'PossibleCheatingDetected' which is set to true once cheating has been detected.

    In This Article
    Back to top GuardingPearSoftware documentation