You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何获取SystemClock.elapsedRealtime()实现防篡改离线游戏计时

获取系统重启后运行时长,实现离线防篡改游戏计时器

核心思路

系统自重启后的运行时长(Uptime)是独立于系统时间的指标,修改系统时间不会改变它。我们可以通过各平台原生API获取该值,再结合PlayerPrefs记录游戏每次退出时的Uptime,重启后计算差值即可得到游戏累计运行时间——这就是你看到的Elapsed_stamp变量的作用逻辑。

各平台Uptime获取实现

Windows平台

调用kernel32.dll的GetTickCount64()获取系统启动以来的毫秒数:

using System.Runtime.InteropServices;

public static class SystemUptime
{
    [DllImport("kernel32.dll")]
    private static extern ulong GetTickCount64();

    public static ulong GetUptimeMilliseconds()
    {
        return GetTickCount64();
    }
}

macOS/Linux平台

用Mono的SystemInformation直接获取,或通过系统原生接口实现:

using System.Windows.Forms;

public static ulong GetUptimeMilliseconds()
{
    return (ulong)SystemInformation.TickCount;
}

macOS原生调用版本:

using System.Runtime.InteropServices;

public static class SystemUptime
{
    [DllImport("libc.dylib")]
    private static extern int sysctlbyname(string name, IntPtr oldp, ref uint oldlen, IntPtr newp, uint newlen);

    public static ulong GetUptimeMilliseconds()
    {
        uint len = sizeof(long);
        IntPtr ptr = Marshal.AllocHGlobal((int)len);
        sysctlbyname("kern.boottime", ptr, ref len, IntPtr.Zero, 0);
        long bootTime = Marshal.ReadInt64(ptr);
        Marshal.FreeHGlobal(ptr);
        long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        return (ulong)(now - bootTime) * 1000;
    }
}

Android平台

调用Android系统的SystemClock.elapsedRealtime():

using UnityEngine;

public static ulong GetUptimeMilliseconds()
{
    AndroidJavaClass systemClock = new AndroidJavaClass("android.os.SystemClock");
    return (ulong)systemClock.CallStatic<long>("elapsedRealtime");
}

iOS平台

通过mach_absolute_time()转换为实际运行毫秒数:

using System.Runtime.InteropServices;
using UnityEngine;

public static class SystemUptime
{
    [DllImport("libSystem.dylib")]
    private static extern uint mach_absolute_time();

    [DllImport("libSystem.dylib")]
    private static extern void mach_timebase_info(ref TimebaseInfo info);

    private struct TimebaseInfo
    {
        public uint numer;
        public uint denom;
    }

    public static ulong GetUptimeMilliseconds()
    {
        TimebaseInfo info = new TimebaseInfo();
        mach_timebase_info(ref info);
        ulong absoluteTime = mach_absolute_time();
        ulong nanoseconds = absoluteTime * (ulong)info.numer / (ulong)info.denom;
        return nanoseconds / 1000000;
    }
}

结合PlayerPrefs实现计时器逻辑

每次游戏退出时记录当前Uptime和累计时间,启动时计算差值更新总时长:

using UnityEngine;

public class GameTimer : MonoBehaviour
{
    private const string Prefs_UptimeStamp = "Elapsed_stamp";
    private const string Prefs_TotalGameTime = "Total_Game_Time";

    private ulong _lastUptime;
    private double _totalGameTime;

    void Start()
    {
        if (PlayerPrefs.HasKey(Prefs_UptimeStamp) && PlayerPrefs.HasKey(Prefs_TotalGameTime))
        {
            _lastUptime = (ulong)PlayerPrefs.GetInt(Prefs_UptimeStamp);
            _totalGameTime = PlayerPrefs.GetFloat(Prefs_TotalGameTime);
        }
        else
        {
            _lastUptime = SystemUptime.GetUptimeMilliseconds();
            _totalGameTime = 0;
        }
    }

    void Update()
    {
        ulong currentUptime = SystemUptime.GetUptimeMilliseconds();
        if (currentUptime > _lastUptime)
        {
            double delta = (currentUptime - _lastUptime) / 1000.0;
            _totalGameTime += delta;
            _lastUptime = currentUptime;
        }
    }

    void OnApplicationQuit()
    {
        PlayerPrefs.SetInt(Prefs_UptimeStamp, (int)_lastUptime);
        PlayerPrefs.SetFloat(Prefs_TotalGameTime, (float)_totalGameTime);
        PlayerPrefs.Save();
    }

    public double GetTotalGameTime()
    {
        return _totalGameTime;
    }
}

关键注意事项

  • 用Application.platform做平台分支判断,确保各平台调用对应Uptime获取方法。
  • PlayerPrefs存储为明文,可通过简单异或加密存储值,防止玩家直接修改文件篡改时间。
  • 优先使用64位返回值,避免32位Uptime变量溢出问题。

内容的提问来源于stack exchange,提问作者Xordaraxus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:15:55