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

Unity中如何实现队伍属性、背包数据及游戏标记的存储与加载

解决方案

1. 核心前提:给每个角色配置唯一标识

所有角色的Player脚本新增固定唯一ID字段,后续所有数据匹配都基于这个ID:

public class Player : MonoBehaviour
{
    // 每个角色配置固定不重复的ID,比如主角填"role_main",法师队友填"role_mage"
    public string roleId;
    // 原有其他属性保留
    public int WP;
    public float spe;
    public Vector3 position;
}

2. 重构数据结构适配多维度存储

把单角色数据扩展为全局存档根结构,同时兼容角色数据、背包、杂项标记三类需求:

using System.Collections.Generic;
using UnityEngine;
using System;

// 单角色存档数据
[Serializable]
public class CharacterSaveData
{
    public string roleId;
    public int wp;
    public float spe;
    public Vector3 pos;

    public CharacterSaveData(Player play)
    {
        roleId = play.roleId;
        wp = play.WP;
        spe = play.spe;
        pos = play.transform.position;
    }
}

// 背包物品存档数据
[Serializable]
public class InventoryItemData
{
    public int itemId;
    public int count;
}

// 杂项标记存档数据(适配Unity JsonUtility序列化规则)
[Serializable]
public class GameFlagData
{
    public string flagKey;
    public bool flagValue;
}

// 全局存档根结构
[Serializable]
public class GameSaveData
{
    // 所有已解锁角色的数据
    public List<CharacterSaveData> characterDatas = new List<CharacterSaveData>();
    // 背包数据
    public List<InventoryItemData> inventoryDatas = new List<InventoryItemData>();
    // 全局杂项标记(剧情进度、宝箱状态等)
    public List<GameFlagData> gameFlags = new List<GameFlagData>();
}

3. 重写存档读写逻辑

using System.IO;
using System.Collections.Generic;
using UnityEngine;

public static class SaveJson
{
    private static string SavePath => Application.dataPath + "/save.txt";
    private static string TempPath => Application.dataPath + "/temp.txt";

    // 全局保存方法:传入当前所有队伍角色、背包数据、全局标记
    public static void Save(List<Player> teamMembers, List<InventoryItemData> inventory, List<GameFlagData> flags)
    {
        GameSaveData saveData = new GameSaveData();
        // 写入所有角色数据
        foreach (var player in teamMembers)
        {
            saveData.characterDatas.Add(new CharacterSaveData(player));
        }
        // 写入背包和标记数据
        saveData.inventoryDatas = inventory;
        saveData.gameFlags = flags;
        
        string json = JsonUtility.ToJson(saveData);
        File.WriteAllText(SavePath, json);
        Debug.Log("存档完成: " + json);
    }

    // 全局加载方法:传入当前已解锁的所有队伍角色,返回背包和标记数据
    public static (List<InventoryItemData> inventory, List<GameFlagData> flags) Load(List<Player> currentTeam)
    {
        if (!File.Exists(SavePath))
        {
            Debug.Log("无存档文件,返回默认数据");
            return (new List<InventoryItemData>(), new List<GameFlagData>());
        }

        string json = File.ReadAllText(SavePath);
        GameSaveData saveData = JsonUtility.FromJson<GameSaveData>(json);
        
        // 给当前已解锁角色匹配对应存档数据
        foreach (var player in currentTeam)
        {
            var matchData = saveData.characterDatas.Find(data => data.roleId == player.roleId);
            // 匹配到数据就赋值,没匹配到说明是新解锁角色,直接用初始属性即可
            if (matchData != null)
            {
                player.WP = matchData.wp;
                player.spe = matchData.spe;
                player.transform.position = matchData.pos;
                player.position = matchData.pos;
            }
        }
        
        Debug.Log("读档完成");
        return (saveData.inventoryDatas, saveData.gameFlags);
    }

    // 临时存档逻辑扩展示例
    public static void SaveTemp(List<Player> teamMembers)
    {
        GameSaveData tempData = new GameSaveData();
        foreach (var player in teamMembers)
        {
            tempData.characterDatas.Add(new CharacterSaveData(player));
        }
        string json = JsonUtility.ToJson(tempData);
        File.WriteAllText(TempPath, json);
        Debug.Log("临时存档完成");
    }

    public static void LoadTemp(List<Player> currentTeam)
    {
        if (!File.Exists(TempPath))
        {
            Debug.Log("无临时存档");
            return;
        }
        string json = File.ReadAllText(TempPath);
        GameSaveData tempData = JsonUtility.FromJson<GameSaveData>(json);
        foreach (var player in currentTeam)
        {
            var matchData = tempData.characterDatas.Find(data => data.roleId == player.roleId);
            if (matchData != null)
            {
                player.WP = matchData.wp;
                player.spe = matchData.spe;
            }
        }
        File.Delete(TempPath);
    }
}

4. 动态解锁角色适配方案

新角色解锁时直接使用预设的初始属性初始化即可,不需要做特殊处理,下次触发存档时,新角色的数据会自动加入到存档列表中,后续读档就能正常匹配。

注意事项

  • 所有参与序列化的自定义类必须加[Serializable]属性,否则Unity的JsonUtility无法正常序列化
  • 角色的roleId必须全局唯一,不能重复,否则会出现数据匹配错误
  • 如果需要多存档槽位,只需要修改SavePath的路径规则,加入槽位编号即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:39:04