多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -1,8 +1,8 @@
# 09 · 进度模块
> **命名空间** `BaseGames.Equipment`、`BaseGames.Skills`、`BaseGames.Progression`
> **命名空间** `BaseGames.Player`、`BaseGames.Equipment`、`BaseGames.Skills`、`BaseGames.Progression`
> **程序集** `BaseGames.Equipment`、`BaseGames.Skills`
> **路径** `Assets/Scripts/Equipment/`、`Assets/Scripts/Skills/`
> **路径** `Assets/Scripts/Player/`、`Assets/Scripts/World/`、`Assets/Scripts/Equipment/`、`Assets/Scripts/Skills/`
> **依赖** `BaseGames.Core.Events`、`BaseGames.Combat`、`BaseGames.Player`
---
@@ -33,6 +33,7 @@
> - 原 `Dictionary<string, bool>` 存档方案每次查询需 `.ToString()` 装箱 + 字典哈希,在 AbilityGate.Start() 及 ParrySystem.TryActivateParry() 等热路径产生不必要开销
> - 改为 bitmask 后:存档只存一个 `uint`,查询为单次位运算 `(_flags & ability) != 0`,兼容序列化
> - **新增能力只需追加新的 `1 << N`,禁止修改已有枚举值**(防止存档数据错位)
> - 本节以当前仓库中的 `Assets/Scripts/Player/AbilityType.cs` 为准;历史文档中的旧命名不再作为当前实现事实来源
```csharp
// 路径: Assets/Scripts/Player/AbilityType.cs
@@ -40,36 +41,41 @@
[System.Flags]
public enum AbilityType : uint
{
None = 0,
None = 0,
// 移动
WallCling = 1u << 0,
WallJump = 1u << 1,
Dash = 1u << 2,
AerialDash = 1u << 3, // 空中冲刺(默认锁定,升级后解锁
InvincibleDash= 1u << 4, // 冲刺全程无敌Dash 的升级版,默认锁定)
DoubleJump = 1u << 5,
ClimbVines = 1u << 6,
Swim = 1u << 7, // 游泳LiquidZone 内切换 SwimState
// 移动能力
WallCling = 1u << 0, // 贴墙悬挂
WallJump = 1u << 1, // 墙跳
Dash = 1u << 2, // 地面冲刺
AirDash = 1u << 3, // 空中冲刺(二段冲刺
DoubleJump = 1u << 4, // 二段跳
SuperJump = 1u << 5, // 超级跳(聚气跳)
Swim = 1u << 6, // 游泳(液体中自由移动)
Dive = 1u << 7, // 下劈(空中下突
// 战斗
Parry = 1u << 8,
Spring = 1u << 9, // 灵泉反弹
UseTools = 1u << 10,
// 法术能力
Spell1 = 1u << 8, // 法术槽 1策划自定义
Spell2 = 1u << 9, // 法术槽 2
Spell3 = 1u << 10, // 法术槽 3
// 互动
ReadShrine = 1u << 11,
UseGrapple = 1u << 12,
// 灵魄形态
SpiritForm = 1u << 11, // 灵魄形态切换
SpiritDash = 1u << 12, // 灵魄冲刺(穿透地形)
// 预留扩展位13~31新能力在此追加禁止复用已有值
// 战斗能力
Parry = 1u << 13, // 格挡/弹反
ChargeAttack = 1u << 14, // 蓄力攻击
DownSlash = 1u << 15, // 下斩
// 互动能力
Interact = 1u << 16, // 互动NPC/机关)
FastTravel = 1u << 17, // 快速旅行解锁
// 组合掩码
AllMovement = WallCling | WallJump | Dash | AirDash | DoubleJump | SuperJump | Swim | Dive,
AllSpells = Spell1 | Spell2 | Spell3,
AllSpirit = SpiritForm | SpiritDash,
}
// ── SaveMigrator 兼容说明 ─────────────────────────────────────────────────
// SaveMeta.Version < "2.1" 的存档仍持有 Dictionary<string, bool> Abilities
// SaveMigrator.MigrateV2ToV21 负责将其转换为 AbilityFlags uint
// foreach (var kv in old.Abilities)
// if (kv.Value && Enum.TryParse<AbilityType>(kv.Key, out var a))
// newFlags |= (uint)a;
```
---
@@ -418,10 +424,11 @@ public class WeaponOverrideEffect : ICharmEffect
```csharp
// 路径: Assets/Scripts/Equipment/EquipmentManager.cs
public class EquipmentManager : MonoBehaviour
public class EquipmentManager : MonoBehaviour, ISaveable
{
[Header("配置")]
[SerializeField] private EquipmentConfigSO _config; // 初始 Notch 数量等
[SerializeField] private EquipmentConfigSO _config; // 初始 Notch 数量等
[SerializeField] private CharmCatalogSO _charmCatalog; // CharmSO 查找表Assets/Data/Equipment/CharmCatalog.asset
[Header("Event Channels")]
[SerializeField] private CharmEventChannelSO _onCharmEquipped;
@@ -475,13 +482,38 @@ public class EquipmentManager : MonoBehaviour
_onEquipmentChanged.Raise();
}
public void AddToCollection(string charmId); // 加入收藏(存档)
public void AddToCollection(string charmId)
{
// 通过 _charmCatalog.Find(charmId) 查找 CharmSO去重后加入 _collected
if (_charmCatalog == null) return;
var charm = _charmCatalog.Find(charmId);
if (charm != null && !_collected.Contains(charm)) _collected.Add(charm);
}
public void IncreaseNotches(int amount) => _currentNotchCapacity += amount;
// 存档集成
public EquipmentSaveData GetSaveData();
public void LoadSaveData(EquipmentSaveData data);
// 存档集成ISaveable
public void OnSave(SaveData data)
{
data.Equipment.EquippedCharmIds = _equipped.Select(c => c.charmId).ToArray();
data.Equipment.OwnedCharmIds = _collected.Select(c => c.charmId).ToArray();
data.Equipment.NotchesUsed = UsedNotches;
}
public void OnLoad(SaveData data)
{
// 清除当前装备,恢复 _collected再装备 _equipped
foreach (var c in _equipped.ToList()) UnequipCharm(c);
_collected.Clear();
if (data.Equipment.OwnedCharmIds != null)
foreach (var id in data.Equipment.OwnedCharmIds) AddToCollection(id);
if (data.Equipment.EquippedCharmIds != null)
foreach (var id in data.Equipment.EquippedCharmIds)
{
var charm = _charmCatalog?.Find(id);
if (charm != null) TryEquipCharm(charm);
}
_onEquipmentChanged.Raise();
}
}
```
@@ -531,6 +563,7 @@ public class ToolSlotManager : MonoBehaviour, ISaveable
[SerializeField] private ToolSO[] _slots = new ToolSO[SlotCount];
[SerializeField] private int[] _remainingUses = new int[SlotCount]; // -1 = 无限
[SerializeField] private ToolCatalogSO _toolCatalog; // ToolSO 查找表Assets/Data/Equipment/ToolCatalog.asset
[SerializeField] private ToolUsedEventChannelSO _onToolUsed;
// 当前冷却倒计时(秒)
@@ -582,7 +615,13 @@ public class ToolSlotManager : MonoBehaviour, ISaveable
data.Tools.ToolSlot0 = _slots[0]?.toolId; // 注:工具数据归属 SaveData.Tools不在 Equipment
data.Tools.ToolSlot1 = _slots[1]?.toolId;
}
public void OnLoad(SaveData data) { /* 从 data.Tools 恢复 ToolSO 引用 */ }
public void OnLoad(SaveData data)
{
// 重置冷却,通过 _toolCatalog.Find() 恢复两个槽位的 ToolSO 引用
for (int i = 0; i < SlotCount; i++) _cooldowns[i] = 0f;
EquipTool(0, _toolCatalog?.Find(data.Tools.ToolSlot0));
EquipTool(1, _toolCatalog?.Find(data.Tools.ToolSlot1));
}
}
// 可选接口:带冷却时间的工具