원클릭으로
save
存档序列化规则,包含JsonUtility序列化规范、数据类目录规范、存档系统架构。Invoke when working on save data, serialization, SaveData classes, or data persistence.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
存档序列化规则,包含JsonUtility序列化规范、数据类目录规范、存档系统架构。Invoke when working on save data, serialization, SaveData classes, or data persistence.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
AI策略系统规则,包含分层决策架构、HeroDispatcher、StrategicDecider等组件规范。Invoke when working on AI logic, hero dispatching, strategic decisions, or AI-related code.
战斗系统规则,包含Tick驱动架构、ChessAction队列、IRecoverable接口、BattleRandom规范。Invoke when working on combat system, ChessAction, Buff, Skill, or battle-related code.
代码地图,包含项目目录结构、文件用途说明、关键类位置索引。Invoke when navigating the codebase, locating files, or understanding project structure.
MapTool地图工具规则,包含城市邻接查询、前线判断、距离计算等规范。Invoke when working with city adjacency, frontline detection, distance calculation, or map-related logic.
| name | save |
| description | 存档序列化规则,包含JsonUtility序列化规范、数据类目录规范、存档系统架构。Invoke when working on save data, serialization, SaveData classes, or data persistence. |
[Serializable] 标记需要序列化的类[NonSerialized] 标记运行时引用(如 viewObj, owner 等Unity对象引用和回调)[SerializeReference] 标记多态序列化字段(如 List<ChessAction> actions)JsonUtility 进行序列化/反序列化SaveData, SaveCityData, SaveHeroData 等)必须可被 JsonUtility 序列化[NonSerialized](如 SaveCityData.actions、SaveForceData.posResCache)SaveForceData.phase、SaveForceData.planConfirmed)BattleStatManager.currentInstance、Chess.viewObj)SaveForceData.warPlans 标记为 [NonSerialized],因为战斗计划是每回合临时生成的项目中仅有一处使用 [SerializeReference]:
// BattleManager.cs
[SerializeReference]
List<ChessAction> actions // 多态序列化 ChessAction 子类
这是为了支持 ChessAction 的多态序列化(不同子类需保持类型信息)。
由于 JsonUtility 不支持 Dictionary<K,V> 序列化,项目采用两种替代方案:
SaveCityData.devAssignments 用 List<DevAssignmentData> 存储映射,通过 GetDevIdByHeroId() 查询SaveCityData.actions 等不需要持久化的映射直接用 Dictionary 并标记不序列化SaveDatas/ 目录下
SaveData, SaveForceData, SaveCityData, SaveHeroData, WarTeamData, WarPlanData, DevAssignmentDataPO/ 目录下
SignalData, AttrInfo, BattleCardData, ArmsType, TurnPhase 等[Serializable]
public class SaveData
{
public List<SaveForceData> forces;
public List<SaveCityData> cities;
public List<SaveHeroData> heros;
public BattleStatManager battleStatManager;
public int round;
public int currentForceIndex;
}
[Serializable]
public class SaveForceData
{
// 持久化字段
public int forceId;
public bool isPlayer;
public bool isEliminated;
public float gold;
// 非序列化字段(运行时状态)
[NonSerialized] public TurnPhase phase = TurnPhase.None;
[NonSerialized] public List<WarPlanData> warPlans;
[NonSerialized] public bool planConfirmed = false;
[NonSerialized] private Dictionary<string, float> posResCache;
[NonSerialized] private Dictionary<string, int> resUsedCache;
}
加载后通过 InitRuntimeState() 重新初始化 [NonSerialized] 字段。
[Serializable]
public class SaveCityData
{
// 持久化字段
public int cityId, forceId, level, exp, ownerHeroId;
public float soldier, happy, food, wall;
public List<DevAssignmentData> devAssignments;
// 非序列化字段
[NonSerialized] public Dictionary<int, int> actions;
}
devAssignments 通过 SetDevAssignment() / RemoveDevAssignment() / ClearDevAssignments() 管理,修改后触发 RecalculatePosRes()。
public enum HeroState { Normal, Wild, Catched }
[Serializable]
public class SaveHeroData
{
public int heroId, exp, cityId, forceId, armsId;
public HeroState state;
public int loyalty;
public int str, inte, fair, charm, leadShip; // 五维属性
}
InitAttrsFromConfig() 在属性为零值时从配置表回填,实现"存档优先、配置兜底"的兼容策略。
[Serializable]
public class WarTeamData
{
public int heroId1, heroId2, heroId3; // 固定3个英雄槽位
public int armsId;
public int targetCityId;
}
public class WarPlanData
{
public List<WarTeamData> teams;
}
注意:WarPlanData 本身没有 [Serializable] 标记,被 SaveForceData.warPlans([NonSerialized])引用,是纯运行时数据。
[Serializable]
public class DevAssignmentData
{
public int heroId;
public int devId;
}
虽然定义在 Combat/ 目录下,但作为 SaveData 的字段被一起序列化。包含 BattleRecord 和 BattleStat 内部类。
| 操作 | 方法 |
|---|---|
| 保存 | GameManager.SaveToFile() |
| 加载 | GameManager.LoadFromSave() |
| 检测 | GameManager.IsGameSaveExist() |
// 保存
string json = JsonUtility.ToJson(SaveData);
File.WriteAllText(savePath, json);
// 加载
SaveData saveData = JsonUtility.FromJson<SaveData>(json);
SaveData = saveData;
foreach (var forceData in SaveData.forces)
forceData.InitRuntimeState(); // 重新初始化运行时状态
Application.persistentDataPath + "/game_save.json"JsonUtility.ToJson() / JsonUtility.FromJson<T>() 全量序列化/反序列化InitRuntimeState() 恢复 [NonSerialized] 字段| 操作 | 方法 |
|---|---|
| 保存 | BattleManager.SaveToFile(filePath) |
| 加载 | BattleManager.LoadFromFile(filePath) |
// 保存
string json = JsonUtility.ToJson(this);
File.WriteAllText(filePath, json);
// 加载(覆盖式)
JsonUtility.FromJsonOverwrite(json, this);
foreach (var chess in chessList) chess.OnRecover();
foreach (var missile in missileList) missile.OnRecover();
battlereplayer{battleId}.json.jsonJsonUtility.FromJsonOverwrite() 覆盖式反序列化(不创建新实例,直接覆盖现有对象字段)OnRecover() 接口恢复运行时引用SaveHeroData.InitAttrsFromConfig() 利用此特性:属性为零值时从配置表回填,保证旧存档兼容SaveData 字段时需考虑旧存档的零值兼容问题GameManager.NewGame() 结束时保存GameManager.ConfirmPlan() 确认计划后保存SaveCityData.Occupy() 城市被占领后保存SaveData 字段时,需考虑旧存档兼容(JsonUtility 反序列化时缺失字段为零值)SaveCityData.actions 使用 [NonSerialized],不会持久化DevAssignmentData 使用列表存储,通过 SetDevAssignment / RemoveDevAssignment 管理List<数据类> 而非 DictionarySaveData 及其子类中存储 Unity 对象引用PO/ 目录下,必须放在 SaveDatas/ 目录下[NonSerialized]