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

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);
    }
}

问题根源

  1. 循环加载死循环:如果脚本挂载在所有游戏场景中,每次加载存档场景后,该场景内的SceneLoader会再次读取PlayerPrefs并尝试加载同一个场景,导致无限重复加载,引发游戏反复重启。
  2. 默认场景未匹配需求:原代码默认场景是DefaultSceneName,未设置为前置剧情场景。
  3. 存档时机单一:仅靠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();
        }
    }
}

代码使用说明

  1. 配置场景名称:在Inspector面板中,将firstLaunchScene设置为你的前置剧情场景名称(比如IntroScene)。
  2. Build Settings配置:确保BootScene、前置剧情场景、所有游戏关卡都添加到File > Build Settings的场景列表中,且BootScene排在最顶部作为启动场景。
  3. 关卡切换时存档:在你的关卡切换逻辑中调用SceneLoader.SaveCurrentScene(),比如玩家完成前置剧情进入Level 1时:
    // 示例:切换到Level1前存档当前进度
    SceneLoader.SaveCurrentScene();
    SceneManager.LoadScene("Level1");
    
  4. 避免重复挂载:脚本仅需挂载在BootScene的物体上,不要在其他游戏场景中挂载,彻底避免循环加载问题。

关键优化点

  • 消除循环加载:通过启动场景统一处理加载逻辑,其他场景不挂载该脚本,避免重复触发加载。
  • 多时机存档:除退出时存档,增加后台暂停时的存档,同时支持主动调用存档,提升进度保存安全性。
  • 场景存在性检查:避免加载不存在的场景导致报错。
  • 首次启动判断:通过SavedScene是否为空判断首次启动,自动加载前置剧情。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:51:33