Unity游戏重启加载上次退出场景的问题及代码修复需求
问题与解决方案
问题描述
我正在制作一款恐怖游戏,游戏开头有一段较长的前置剧情,效果不错,但每次进入游戏都播放该剧情会令人烦躁。我希望首次启动时播放该剧情,后续启动则加载上次退出时的场景,这也能解决存档问题——若玩家已到达Level 2,再次登录时直接从该场景开始。
我尝试用PlayerPrefs实现,但到达需存档的关卡时游戏多次重启,无法正常运行。以下是我的无效代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneLoader : MonoBehaviour { private string activeSceneName; void Start() { activeSceneName = PlayerPrefs.GetString("ActiveScene", "DefaultSceneName"); StartCoroutine(LoadSavedScene()); } void OnApplicationQuit() { activeSceneName = SceneManager.GetActiveScene().name; PlayerPrefs.SetString("ActiveScene", activeSceneName); PlayerPrefs.Save(); } IEnumerator LoadSavedScene() { yield return new WaitForSeconds(0.5f); // Wait for a short time to allow the scene to load completely SceneManager.LoadScene(activeSceneName); } }
问题根源
- 循环加载死循环:如果脚本挂载在所有游戏场景中,每次加载存档场景后,该场景内的
SceneLoader会再次读取PlayerPrefs并尝试加载同一个场景,导致无限重复加载,引发游戏反复重启。 - 默认场景未匹配需求:原代码默认场景是
DefaultSceneName,未设置为前置剧情场景。 - 存档时机单一:仅靠
OnApplicationQuit存档,若游戏崩溃或进程被强制结束,存档会丢失;且关卡切换时未主动存档,可能导致进度未保存。
修复后的完整代码
步骤1:创建启动场景(BootScene)
先创建空场景BootScene作为游戏入口,该场景仅用于判断加载目标,不放置游戏内容。将下方脚本挂载到该场景的空物体上。
步骤2:修复后的SceneLoader代码
using UnityEngine; using UnityEngine.SceneManagement; public class SceneLoader : MonoBehaviour { // 首次启动时加载的前置剧情场景名称 [Header("首次启动场景")] public string firstLaunchScene = "IntroScene"; // 标记是否已完成加载判断,避免重复执行 private bool hasLoaded = false; void Start() { // 仅执行一次加载逻辑 if (hasLoaded) return; hasLoaded = true; LoadSavedScene(); } // 加载存档场景或首次启动场景 private void LoadSavedScene() { // 读取存档场景名称,无存档则返回空字符串 string savedScene = PlayerPrefs.GetString("SavedScene", ""); // 判断是否有有效存档场景 if (!string.IsNullOrEmpty(savedScene) && SceneExists(savedScene)) { SceneManager.LoadScene(savedScene); } else { // 首次启动,加载前置剧情场景 SceneManager.LoadScene(firstLaunchScene); } } // 检查场景是否在Build Settings中 private bool SceneExists(string sceneName) { for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) { string path = SceneUtility.GetScenePathByBuildIndex(i); string scene = System.IO.Path.GetFileNameWithoutExtension(path); if (scene == sceneName) { return true; } } return false; } // 主动调用该方法存档(关卡切换时使用) public static void SaveCurrentScene() { string currentScene = SceneManager.GetActiveScene().name; PlayerPrefs.SetString("SavedScene", currentScene); PlayerPrefs.Save(); } // 退出时自动存档 private void OnApplicationQuit() { SaveCurrentScene(); } // 游戏暂停到后台时存档(可选,提升安全性) private void OnApplicationPause(bool pauseStatus) { if (pauseStatus) { SaveCurrentScene(); } } }
代码使用说明
- 配置场景名称:在Inspector面板中,将
firstLaunchScene设置为你的前置剧情场景名称(比如IntroScene)。 - Build Settings配置:确保
BootScene、前置剧情场景、所有游戏关卡都添加到File > Build Settings的场景列表中,且BootScene排在最顶部作为启动场景。 - 关卡切换时存档:在你的关卡切换逻辑中调用
SceneLoader.SaveCurrentScene(),比如玩家完成前置剧情进入Level 1时:// 示例:切换到Level1前存档当前进度 SceneLoader.SaveCurrentScene(); SceneManager.LoadScene("Level1"); - 避免重复挂载:脚本仅需挂载在
BootScene的物体上,不要在其他游戏场景中挂载,彻底避免循环加载问题。
关键优化点
- 消除循环加载:通过启动场景统一处理加载逻辑,其他场景不挂载该脚本,避免重复触发加载。
- 多时机存档:除退出时存档,增加后台暂停时的存档,同时支持主动调用存档,提升进度保存安全性。
- 场景存在性检查:避免加载不存在的场景导致报错。
- 首次启动判断:通过
SavedScene是否为空判断首次启动,自动加载前置剧情。
内容的提问来源于stack exchange,提问作者LIMON
相关产品推荐
相关产品推荐

