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

Unity3D(C#)手游如何实现关卡保存与加载功能?

Unity C# 关卡进度保存与加载实现方案

方案选型

根据你的需求复杂度,可以选两种常用的实现方式:

  • 仅需存储已解锁最大关卡、最近游玩关卡ID这类简单数据:直接用Unity原生PlayerPrefs即可,无需处理文件读写逻辑,跨平台适配已经由Unity封装完成
  • 需存储每个关卡的星级、收集物、通关时长等复杂维度数据:使用JSON序列化+本地文件存储的方案,扩展性更强

具体实现步骤

1. 基于PlayerPrefs的轻量实现

适合需求简单的中小体量游戏,代码量极小:

保存逻辑

调用时机:关卡完成进入下一关、游戏退出/切后台时

public void SaveLevelProgress(int clearedLevelId, int currentPlayedLevelId)
{
    // 存储已解锁的最大关卡ID,比如通关关卡3则解锁关卡4
    PlayerPrefs.SetInt("UnlockedMaxLevel", clearedLevelId + 1);
    // 存储最近游玩的关卡ID,下次启动游戏可以直接跳转
    PlayerPrefs.SetInt("LatestPlayedLevel", currentPlayedLevelId);
    // 立即写入磁盘,避免游戏异常崩溃导致存档丢失
    PlayerPrefs.Save();
}

加载逻辑

调用时机:游戏启动、进入关卡选择界面时

public (int unlockedMaxLevel, int latestPlayedLevel) LoadLevelProgress()
{
    // 第二个参数为默认值,无存档时默认解锁第一关
    int unlockedMaxLevel = PlayerPrefs.GetInt("UnlockedMaxLevel", 1);
    int latestPlayedLevel = PlayerPrefs.GetInt("LatestPlayedLevel", 1);
    return (unlockedMaxLevel, latestPlayedLevel);
}

自动触发保存配置

  • 关卡结算界面点击「下一关」按钮时,直接调用SaveLevelProgress传入对应关卡ID即可
  • 游戏退出/切后台的自动保存,可以挂载到MonoBehaviour的OnApplicationQuit、OnApplicationPause生命周期函数中,避免切后台被系统杀进程导致进度丢失

2. 基于JSON序列化的复杂进度实现

适合需要存储多维度关卡数据的项目,可自由扩展字段:

第一步:定义序列化数据结构

using System;
using System.Collections.Generic;

// 总关卡进度数据
[Serializable]
public class LevelProgressData
{
    public int unlockedMaxLevel;
    public int latestPlayedLevel;
    // Key为关卡ID,Value为对应关卡的详细数据
    public Dictionary<int, SingleLevelInfo> levelInfoMap;
}

// 单个关卡的详细数据
[Serializable]
public class SingleLevelInfo
{
    public bool isCleared;
    // 星级评分1-3星
    public int starCount;
    // 关卡内收集的道具数量
    public int collectedItemCount;
    // 最短通关时长
    public float fastestClearTime;
}

第二步:实现存读盘管理器

using System.IO;
using UnityEngine;

public class LevelSaveManager : MonoBehaviour
{
    public static LevelSaveManager Instance;
    private string saveFilePath;

    private void Awake()
    {
        Instance = this;
        // persistentDataPath为Unity跨平台可写目录,不会被系统随意清理
        saveFilePath = Path.Combine(Application.persistentDataPath, "LevelProgress.dat");
    }

    // 保存进度
    public void SaveProgress(LevelProgressData data)
    {
        string jsonContent = JsonUtility.ToJson(data);
        // 可选:对JSON做简单异或加密,防止用户直接修改本地存档
        File.WriteAllText(saveFilePath, jsonContent);
    }

    // 加载进度
    public LevelProgressData LoadProgress()
    {
        if (!File.Exists(saveFilePath))
        {
            // 无存档时返回初始化的新存档
            return new LevelProgressData()
            {
                unlockedMaxLevel = 1,
                latestPlayedLevel = 1,
                levelInfoMap = new Dictionary<int, SingleLevelInfo>()
            };
        }
        string jsonContent = File.ReadAllText(saveFilePath);
        // 对应加密逻辑的解密步骤
        return JsonUtility.FromJson<LevelProgressData>(jsonContent);
    }

    // 退出游戏自动存盘
    private void OnApplicationQuit()
    {
        // 传入当前内存中的进度数据即可
        // SaveProgress(currentRuntimeProgress);
    }

    // 切后台自动存盘
    private void OnApplicationPause(bool isPause)
    {
        if (isPause)
        {
            // SaveProgress(currentRuntimeProgress);
        }
    }
}

注意事项

  • PlayerPrefs仅适合存轻量数据,不要存储大量复杂结构,且本身是明文存储,不要放敏感内容
  • 不要把存档存在Application.dataPath路径下,项目打包后该路径为只读,会导致存盘失败
  • 避免游戏运行过程中频繁调用存盘接口,仅在关卡结算、退出、切后台三个节点调用即可,减少性能损耗
  • 对存档安全性要求高的项目,可以给存档内容加上MD5校验位,加载时先校验内容是否被篡改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:45:09