Class TimeCheatingDetector
Allows to detect time cheating using time from any properly configured server (almost all servers around the web).
[AddComponentMenu("Code Stage/Anti-Cheat Toolkit/Time Cheating Detector")]
[DisallowMultipleComponent]
[HelpURL("https://docs.codestage.net/actk/manual/detectors.html#time-cheating-detector")]
public class TimeCheatingDetector : ACTkDetectorBase<TimeCheatingDetector>
- Inheritance
-
objectObjectComponentBehaviourMonoBehaviourTimeCheatingDetector
- Inherited Members
Remarks
Requires Internet connection and appropriate android.permission.INTERNET permission when used on Android platform.
Automatically switches to the current domain on WebGL (if RequestUrl leads to any external resource) to avoid CORS limitation.
Make sure your server returns correct Date response header value in case of problems.
Doesn't detects cheating if there is no Internet connection, should work even with weak connection though.
Just add it to any GameObject as usual or through the GameObject > Create Other > Code Stage > Anti-Cheat Toolkit
menu to get started.
You can use detector completely from inspector without writing any code except the actual reaction on cheating.
⚠️ Important: Avoid using detectors from code at the Awake phase.
// Basic usage - start detection with callback
void Start()
{
TimeCheatingDetector.StartDetection(OnTimeCheatingDetected);
}
private void OnTimeCheatingDetected(CheckResult result, ErrorKind error)
{
if (result == CheckResult.WrongTimeDetected)
{
Debug.Log("Time cheating detected!");
// Handle the detection - ban player, show warning, etc.
}
else if (error != ErrorKind.NoError)
{
Debug.LogWarning($"Time check failed: {error}");
}
}
// Advanced usage with custom settings
void Start()
{
// Start with custom interval and callback
TimeCheatingDetector.StartDetection(5f, OnTimeCheatingDetected);
}
private void OnTimeCheatingDetected(CheckResult result, ErrorKind error)
{
switch (result)
{
case CheckResult.WrongTimeDetected:
Debug.Log("Player changed system time!");
break;
case CheckResult.RealCheatDetected:
Debug.Log("Real time cheat detected!");
break;
case CheckResult.OnlineTimeError:
Debug.LogWarning("Failed to get online time");
break;
}
}
// Manual time check
void CheckTimeManually()
{
StartCoroutine(TimeCheatingDetector.ForceCheckEnumerator((result, error) =>
{
if (result == CheckResult.WrongTimeDetected)
{
Debug.Log("Manual time check detected cheating!");
}
}));
}
// Using custom server URL
void StartWithCustomServer()
{
var detector = TimeCheatingDetector.AddToSceneOrGetExisting();
detector.RequestUrl = "https://your-server.com/time";
detector.StartDetection(OnTimeCheatingDetected);
}
Fields
ComponentName
public const string ComponentName = "Time Cheating Detector"
Field Value
- string
ignoreSetCorrectTime
Ignore case when time changes to be in sync with online correct time.
[Tooltip("Ignore case when time changes to be in sync with online correct time. Wrong time threshold is taken into account.")]
public bool ignoreSetCorrectTime
Field Value
- bool
Remarks
Wrong time threshold is taken into account.
interval
Time (in minutes) between detector checks. Set to 0 to disable automatic time checks and use ForceCheck(), ForceCheckEnumerator() or ForceCheckTask() to manually run a check.
[Header("Settings in minutes")]
[Tooltip("Time (in minutes) between detector checks.")]
[Range(0, 60)]
public float interval
Field Value
- float
realCheatThreshold
Maximum allowed difference between subsequent measurements, in minutes.
[Tooltip("Maximum allowed difference between subsequent measurements, in minutes.")]
[FormerlySerializedAs("threshold")]
[Range(10, 180)]
public int realCheatThreshold
Field Value
- int
requestMethod
Method to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
[Tooltip("Method to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.")]
public TimeCheatingDetector.RequestMethod requestMethod
Field Value
timeoutSeconds
Online time request timeout in seconds. Request will be automatically aborted if server will not response in specified time.
[Tooltip("Online time request timeout in seconds.")]
public int timeoutSeconds
Field Value
- int
wrongTimeThreshold
Maximum allowed difference between local and online time, in minutes.
[Tooltip("Maximum allowed difference between local and online time, in minutes.")]
[Range(1, 180)]
public int wrongTimeThreshold
Field Value
- int
Remarks
If online and local time difference exceed this threshold, detector will raise an event with
Properties
IsCheckingForCheat
Allows to check if cheating check is currently in process.
public bool IsCheckingForCheat { get; }
Property Value
- bool
LastDetectionInfo
Holds detailed information about latest triggered detection.
public TimeCheatingDetectionInfo LastDetectionInfo { get; }
Property Value
Remarks
Provides information about the check result and error kind that triggered the time cheating detection.
LastError
Last detector error kind. Will be ErrorKind.NoError if there were no errors.
public TimeCheatingDetector.ErrorKind LastError { get; }
Property Value
LastOnlineTimeResult
Complete response data for the last time request.
public TimeCheatingDetector.OnlineTimeResult LastOnlineTimeResult { get; }
Property Value
LastResult
Last check result. Check LastError if this has value of CheckResult.Error.
public TimeCheatingDetector.CheckResult LastResult { get; }
Property Value
RequestUrl
Absolute URL which will return correct Date in response header to the HEAD request (nearly any popular web server out there including google.com, microsoft.com etc.).
public string RequestUrl { get; set; }
Property Value
- string
Methods
AddToSceneOrGetExisting()
Creates new instance of the detector at scene if it doesn't exists. Make sure to call NOT from Awake phase.
public static TimeCheatingDetector AddToSceneOrGetExisting()
Returns
- TimeCheatingDetector
New or existing instance of the detector.
Dispose()
Stops and completely disposes detector component.
public static void Dispose()
Remarks
On dispose Detector follows 2 rules:
- if Game Object's name is "Anti-Cheat Toolkit Detectors": it will be automatically
destroyed if no other Detectors left attached regardless of any other components or children;
- if Game Object's name is NOT "Anti-Cheat Toolkit Detectors": it will be automatically destroyed only if it has neither other components nor children attached;
ForceCheck()
Allows to manually execute cheating check. Restarts interval.
public bool ForceCheck()
Returns
- bool
True if check was started.
Remarks
Listen for detector events to know about check result.
ForceCheckEnumerator()
Allows to manually execute cheating check and wait for the completion within coroutine. Restarts interval.
public IEnumerator ForceCheckEnumerator()
Returns
- IEnumerator
Examples
StartCoroutine(MakeForcedCheck());
private IEnumerator MakeForcedCheck()
{
yield return TimeCheatingDetector.Instance.ForceCheckEnumerator();
// check TimeCheatingDetector.Instance.LastResult
// ...
}
Remarks
Use inside of the coroutine and check LastResult property after yielding this method. Detector events will be invoked too.
ForceCheckTask()
Allows to manually execute cheating check and wait for the completion within async method. Restarts interval.
public Task<TimeCheatingDetector.CheckResult> ForceCheckTask()
Returns
Examples
MakeForcedCheckAsync();
private async void MakeForcedCheckAsync()
{
var result = await TimeCheatingDetector.Instance.ForceCheckTask();
// check result
// ...
}
Remarks
Await this method in async method to wait for the check completion and to get the check result. Detector events will be invoked too. Disabled for WebGL platform.
GetOnlineTimeCoroutine(string, OnlineTimeCallback, RequestMethod)
Receives UTC seconds from url. Runs asynchronously in coroutine.
public static IEnumerator GetOnlineTimeCoroutine(string url, TimeCheatingDetector.OnlineTimeCallback callback, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
urlstringAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
callbackTimeCheatingDetector.OnlineTimeCallbackDelegate to call and pass OnlineTimeResult to.
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- IEnumerator
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
GetOnlineTimeCoroutine(Uri, OnlineTimeCallback, RequestMethod)
Receives UTC seconds from url. Runs asynchronously in coroutine.
public static IEnumerator GetOnlineTimeCoroutine(Uri uri, TimeCheatingDetector.OnlineTimeCallback callback, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
uriUriAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
callbackTimeCheatingDetector.OnlineTimeCallbackDelegate to call and pass OnlineTimeResult to.
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- IEnumerator
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
GetOnlineTimeTask(string, RequestMethod)
Receives UTC seconds from url. Runs asynchronously.
public static Task<TimeCheatingDetector.OnlineTimeResult> GetOnlineTimeTask(string url, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
urlstringAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- Task<TimeCheatingDetector.OnlineTimeResult>
OnlineTimeResult with UTC seconds or error.
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
GetOnlineTimeTask(string, CancellationToken, RequestMethod)
Receives UTC seconds from url. Runs asynchronously.
public static Task<TimeCheatingDetector.OnlineTimeResult> GetOnlineTimeTask(string url, CancellationToken cancellationToken, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
urlstringAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
cancellationTokenCancellationTokenCancellationToken to cancel the operation.
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- Task<TimeCheatingDetector.OnlineTimeResult>
OnlineTimeResult with UTC seconds or error.
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
GetOnlineTimeTask(Uri, RequestMethod)
Receives UTC seconds from url. Runs asynchronously.
public static Task<TimeCheatingDetector.OnlineTimeResult> GetOnlineTimeTask(Uri uri, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
uriUriAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- Task<TimeCheatingDetector.OnlineTimeResult>
OnlineTimeResult with UTC seconds or error.
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
GetOnlineTimeTask(Uri, CancellationToken, RequestMethod)
Receives UTC seconds from url. Runs asynchronously.
public static Task<TimeCheatingDetector.OnlineTimeResult> GetOnlineTimeTask(Uri uri, CancellationToken cancellationToken, TimeCheatingDetector.RequestMethod method = RequestMethod.Head)
Parameters
uriUriAbsolute url to receive time from. Make sure this server has proper Date values in the response headers (almost all popular web sites are suitable).
cancellationTokenCancellationTokenCancellationToken to cancel the operation.
methodTimeCheatingDetector.RequestMethodMethod to use for url request. Use Head method if possible and fall back to get if server does not reply or block head requests.
Returns
- Task<TimeCheatingDetector.OnlineTimeResult>
OnlineTimeResult with UTC seconds or error.
Remarks
Automatically switches to the current domain when running in WebGL to avoid CORS limitation.
IsReadyForForceCheck()
Call this to make sure detector is ready for the ForceCheck() call.
public bool IsReadyForForceCheck()
Returns
- bool
True if you can call the ForceCheck and False otherwise.
StartDetection(TimeCheatingDetectorEventHandler)
Starts detection with specified callback.
public static TimeCheatingDetector StartDetection(TimeCheatingDetector.TimeCheatingDetectorEventHandler cheatCheckedEventHandler = null)
Parameters
cheatCheckedEventHandlerTimeCheatingDetector.TimeCheatingDetectorEventHandlerMethod to call after each cheat check. Pass null if you wish to use event, set in detector inspector.
Returns
Remarks
If you have detector in scene make sure it has empty Detection Event.
Creates a new detector instance if it doesn't exists in scene.
StartDetection(float, TimeCheatingDetectorEventHandler)
Starts detection with specified callback using passed interval.
public static TimeCheatingDetector StartDetection(float intervalMinutes, TimeCheatingDetector.TimeCheatingDetectorEventHandler cheatCheckedEventHandler = null)
Parameters
intervalMinutesfloatTime in minutes between checks. Overrides interval property.
cheatCheckedEventHandlerTimeCheatingDetector.TimeCheatingDetectorEventHandlerMethod to call after each cheat check. Pass null if you wish to use event, set in detector inspector.
Returns
Remarks
If you pass cheatCheckedCallback than make sure you have no filled Detection Event on detector instance in scene to avoid duplicate event calls.
Creates a new detector instance if it doesn't exists in scene.
StopDetection()
- Stops detector. Detector's component remains in the scene. Use Dispose() to completely remove detector.
public static void StopDetection()
TriggerDetection()
Manually triggers cheating detection and invokes assigned events.
[ContextMenu("Trigger detection")]
public void TriggerDetection()
Events
CheatChecked
Gets called after each cheat check and provides results of the check.
public event TimeCheatingDetector.TimeCheatingDetectorEventHandler CheatChecked