You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity开发:移动端应用最小化时内置计时器逻辑在Android失效

我之前在做Unity手游的时候也踩过这个坑——把应用最小化后,内置的计时器直接停了,查了一堆资料才搞定,下面是亲测有效的解决方案,分步骤来:

1. 先调整Unity的基础设置

这是最基础的一步,先让Unity允许应用在后台运行:

  • 打开Unity的Player Settings(Edit > Project Settings > Player),切换到Android标签页
  • Resolution and Presentation里,勾选Run In Background,这个选项会告诉Unity:即使应用不在前台,也继续运行逻辑
  • 再到Other Settings里,找到Background Behavior,设置为Resume(不要选Suspend,否则后台会直接挂起进程)
2. 处理Android系统的后台限制

现在Android(尤其是8.0以上版本)对后台进程的限制非常严格,光靠Unity的设置不够,还得做这些:

  • 添加必要权限:在Player Settings > Android > Other Settings > Configuration > Required Permissions里,添加android.permission.FOREGROUND_SERVICEandroid.permission.WAKE_LOCK(WAKE_LOCK用来保持CPU唤醒,避免系统休眠)
  • 引导用户添加后台白名单:不同品牌手机的路径不一样,比如小米是「设置 > 应用设置 > 应用管理 > 你的应用 > 省电策略 > 无限制」,华为是「设置 > 电池 > 应用启动管理 > 你的应用 > 允许自启动、允许后台活动」。这一步很关键,因为系统层面的杀进程操作,代码很难绕过,必须让用户手动设置。
3. 代码层面优化计时器逻辑

Unity自带的Time.timeTime.deltaTime会在应用挂起时暂停,所以必须改用系统时间来计算计时:

  • System.DateTime.UtcNow来记录起始时间,每次计算流逝时间时直接取当前系统时间和起始时间的差值,这样即使应用被挂起,系统时间还是在走的。示例代码:
private DateTime _timerStartTime;
private float _totalElapsedSeconds;

void Start()
{
    // 记录计时器启动的UTC时间(避免时区问题)
    _timerStartTime = DateTime.UtcNow;
}

void Update()
{
    // 计算从启动到现在的流逝时间,不受Unity挂起影响
    _totalElapsedSeconds = (float)(DateTime.UtcNow - _timerStartTime).TotalSeconds;
    Debug.Log("已运行时长:" + _totalElapsedSeconds + "秒");
}
  • 如果需要在后台持续执行逻辑(比如计时器到点触发事件),可以用Android的前台服务(Foreground Service)——前台服务的优先级比普通后台服务高,不容易被系统杀死。你可以通过Unity的AndroidJavaClass调用Android原生API实现,示例代码(需要配合自己写的Android服务类):
#if UNITY_ANDROID && !UNITY_EDITOR
private AndroidJavaObject _foregroundService;

void Start()
{
    StartAndroidForegroundService();
}

void StartAndroidForegroundService()
{
    // 获取当前Unity Activity
    AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    
    // 调用自定义的前台服务
    AndroidJavaClass serviceClass = new AndroidJavaClass("com.yourgame.package.YourForegroundService");
    _foregroundService = serviceClass.CallStatic<AndroidJavaObject>("getInstance", currentActivity);
    _foregroundService.Call("startForegroundService");
}

void OnDestroy()
{
    // 退出时停止前台服务
    _foregroundService?.Call("stopForegroundService");
}
#endif

注:自定义的Android前台服务需要打包成AAR放到Unity的Plugins/Android文件夹里,核心逻辑是创建服务后调用startForeground()方法,同时显示一个通知(Android要求前台服务必须显示通知)。

4. 测试注意事项
  • 不要用Unity的Remote Debug测试后台行为,Remote模式下的后台逻辑和真机打包后的行为不一致,一定要打包APK安装到真机测试
  • 重点测试Android 10+版本,这些版本的后台限制更严格,要确保计时器在后台能正常走

内容的提问来源于stack exchange,提问作者s.m.m

火山引擎 最新活动