Unity Android项目:如何在应用关闭或后台关闭时触发函数?
解决Unity Android应用关闭/后台被杀死时触发指定函数的方案
1. 结合Unity生命周期+Android原生回调(核心方案)
Unity自带的OnApplicationQuit()和OnApplicationPause()无法覆盖Android应用被后台杀死的场景,必须借助Android原生生命周期回调来补全逻辑。
实现步骤:
(1)编写Android原生模块
创建继承自UnityPlayerActivity的自定义Activity,同时通过AndroidX的ProcessLifecycleOwner监听应用全局生命周期,在应用销毁时通知Unity:
import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.ProcessLifecycleOwner; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; import android.os.Bundle; public class CustomUnityActivity extends UnityPlayerActivity implements LifecycleObserver { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册全局生命周期监听 ProcessLifecycleOwner.get().getLifecycle().addObserver(this); } // 监听应用全局销毁事件 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onAppGlobalDestroy() { // 调用Unity中指定GameObject的方法 UnityPlayer.UnitySendMessage("GameManager", "OnAppTerminated", ""); } // 页面销毁时的双重保险 @Override protected void onDestroy() { super.onDestroy(); UnityPlayer.UnitySendMessage("GameManager", "OnAppTerminated", ""); } }
(2)Unity端接收回调
在Unity中创建一个挂载在持久化GameObject上的脚本,接收Android原生的调用:
using UnityEngine; public class GameManager : MonoBehaviour { // 该方法将被Android原生代码调用 public void OnAppTerminated() { // 这里编写你需要触发的逻辑(比如保存关键数据、上传日志) Debug.Log("应用被关闭或后台被系统杀死"); SavePlayerData(); } private void SavePlayerData() { // 示例:保存玩家数据到本地 PlayerPrefs.SetString("LastSaveTime", System.DateTime.UtcNow.ToString()); PlayerPrefs.Save(); } }
(3)配置Unity项目
- 修改Unity的
AndroidManifest.xml,将默认的UnityPlayerActivity替换为自定义的CustomUnityActivity - 确保项目引入AndroidX Lifecycle库(可在Unity PlayerSettings的Android选项中开启AndroidX支持)
2. 补充:处理低内存强制杀死场景
部分极端场景下(比如系统低内存直接杀死进程),原生回调可能无法触发,可通过启动时校验状态来补全:
using UnityEngine; using System; public class GameManager : MonoBehaviour { private const string PREFS_LAST_PAUSED = "LastBackgroundTime"; private const string PREFS_IN_BACKGROUND = "IsInBackground"; void OnApplicationPause(bool isPaused) { if (isPaused) { // 记录进入后台的时间和状态 PlayerPrefs.SetString(PREFS_LAST_PAUSED, DateTime.UtcNow.ToString()); PlayerPrefs.SetInt(PREFS_IN_BACKGROUND, 1); PlayerPrefs.Save(); } else { // 回到前台时重置状态 PlayerPrefs.SetInt(PREFS_IN_BACKGROUND, 0); PlayerPrefs.Save(); } } void Start() { // 检查上次是否异常退出 if (PlayerPrefs.GetInt(PREFS_IN_BACKGROUND, 0) == 1) { string lastPausedStr = PlayerPrefs.GetString(PREFS_LAST_PAUSED, ""); if (!string.IsNullOrEmpty(lastPausedStr)) { DateTime lastPaused = DateTime.Parse(lastPausedStr); TimeSpan interval = DateTime.UtcNow - lastPaused; // 若间隔超过5分钟,判定为被系统杀死 if (interval.TotalMinutes > 5) { OnAppTerminated(); } } // 重置状态 PlayerPrefs.SetInt(PREFS_IN_BACKGROUND, 0); PlayerPrefs.Save(); } } public void OnAppTerminated() { Debug.Log("检测到应用异常退出,执行处理逻辑"); SavePlayerData(); } private void SavePlayerData() { // 保存逻辑 } }
3. 注意事项
- 真实设备测试:模拟器的进程回收逻辑和真实设备有差异,务必在真机上验证
- 轻量操作:触发的函数不要执行耗时任务,系统可能很快回收进程,优先处理关键数据保存
- 权限配置:确保应用有文件读写权限,避免保存数据失败
内容的提问来源于stack exchange,提问作者Javierdds
相关产品推荐
相关产品推荐

