Universal - Device Time - Monitor (Pro)
Using the current date and time is essential for many applications. However, relying on the clock of the user's device creates trust issues, as users can manipulate it for various purposes such as extending trial periods or gaining advantages in games. AntiCheat has introduced a way to counteract such time manipulation.
Monitor
The 'DeviceTimeMonitor' (class DeviceTimeMonitor, namespace GUPS.AntiCheat.Monitor.Time) observes the device wall-clock time. Across focus and pause transitions, it compares the elapsed DateTime.UtcNow span with the elapsed UnityEngine.Time.realtimeSinceStartup to detect a manipulated device clock. When it finds a deviation, it emits a DeviceTimeStatus to its observers.
Status
The monitor emits a DeviceTimeStatus, which implements IWatchedSubject:
public struct DeviceTimeStatus : IWatchedSubject
{
// Deviation between the device clock and the in-game elapsed time.
public ETimeDeviation Deviation { get; }
}
- Deviation: The device-clock deviation, using the
ETimeDeviationenum:
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
Unlike the game time monitor, this monitor does not sample every frame. Instead, it validates the device time whenever the application transitions through focus or pause:
- When the app loses focus or is paused, it records the current
DateTime.UtcNowandTime.realtimeSinceStartup. - When the app regains focus or resumes, it compares how much device time passed against how much in-game real time passed. If the two differ by more than the tolerance, it builds a
DeviceTimeStatusand notifies observers.
This means observers are notified once per resume, not continuously. Because resuming can involve delays from memory reallocation and thread scheduling, the tolerance avoids reporting those as real deviations.
Configuration
The monitor exposes a single inspector field:
- Tolerance: The allowed deviation in seconds before a difference is reported. Default 5 (recommended 3-10).
Supported platforms
The monitor is available on all platforms.
Requirements
There are no requirements.
How To Use
Attach the 'DeviceTimeMonitor' to a child GameObject of the 'AntiCheat-Monitor' and pair it with the 'DeviceTimeCheatingDetector'.
Add Monitor Component
Add the 'DeviceTimeMonitor' MonoBehavior from the 'GUPS.AntiCheat.Monitor.Time' namespace to your 'AntiCheat-Monitor' GameObject, or better, to a child GameObject.

Add the 'DeviceTimeMonitor' as a Component.
Consume the status in code
Besides pairing the monitor with a detector, you can subscribe your own observer to receive the DeviceTimeStatus 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 DeviceTimeStatusLogger : MonoBehaviour, IObserver<IWatchedSubject>
{
private void Start()
{
var monitor = GetComponentInChildren<DeviceTimeMonitor>();
monitor.Subscribe(this);
}
public void OnNext(IWatchedSubject subject)
{
if (subject is DeviceTimeStatus status)
{
Debug.Log($"Device time deviation: {status.Deviation}");
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
}
Detect Device Time Tampering
To react to the sent status and thus validate the calculated time deviations, you need a detector. To do this, use the 'DeviceTimeCheatingDetector', a detector designed to analyse the status sent by the 'DeviceTimeMonitor' and validate it for cheating.