ワンクリックで
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 ページを確認してインストールできます。
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.
SOC 職業分類に基づく
| 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]