多轮审查和修复
This commit is contained in:
@@ -63,7 +63,7 @@ Week 14: MapModule(Fog of War + 房间探索记录 + 传送点)
|
||||
|
||||
---
|
||||
|
||||
## 2. Week 10:世界互动基础组件
|
||||
## 2. Week 10:世界互动基础组件 ✅ 完成(2026-05-10)
|
||||
|
||||
**参考文档**:`08_WorldModule.md`
|
||||
|
||||
@@ -1012,7 +1012,7 @@ namespace BaseGames.Tutorial
|
||||
|
||||
---
|
||||
|
||||
## 3. Week 11:液态谜题模块
|
||||
## 3. Week 11:液态谜题模块 ✅ 完成(2026-05-11)
|
||||
|
||||
**参考文档**:`21_LiquidPuzzleModule.md`
|
||||
|
||||
@@ -1541,40 +1541,57 @@ public class UnderwaterAudioController : MonoBehaviour
|
||||
|
||||
```csharp
|
||||
// Assets/Scripts/World/Liquid/WaterDangerState.cs
|
||||
// ⚠️ 订阅 LiquidEventChannelSO(携带 LiquidEvent struct,非 LiquidZone 引用)
|
||||
// ⚠️ 使用 PlayerStats.HasAbility 替代 AbilityInventorySO(项目实际 API,无额外 SO 依赖)
|
||||
public class WaterDangerState : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private LiquidPhysicsConfigSO _config;
|
||||
[SerializeField] private AbilityInventorySO _abilityInventory; // 检查 swim 能力
|
||||
[SerializeField] private PlayerStats _playerStats; // 检查 Swim 能力
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited
|
||||
[SerializeField] private FloatEventChannelSO _onDrownProgress; // 0~1 倒计时进度(HUD 用)→ EVT_DrownProgress
|
||||
[SerializeField] private VoidEventChannelSO _onPlayerDrowned; // 触发死亡 → EVT_PlayerDrowned
|
||||
|
||||
private float _drownTimer;
|
||||
private bool _isActive;
|
||||
|
||||
public void OnEnterLiquid(LiquidZone zone)
|
||||
private void OnEnable()
|
||||
{
|
||||
if (zone.Type != LiquidType.Water) return;
|
||||
if (_abilityInventory.HasAbility(AbilityType.Swim)) return;
|
||||
_isActive = true;
|
||||
_drownTimer = _config.DrownTime;
|
||||
if (_onLiquidEntered != null) _onLiquidEntered.OnEventRaised += OnEnterLiquid;
|
||||
if (_onLiquidExited != null) _onLiquidExited.OnEventRaised += OnExitLiquid;
|
||||
}
|
||||
|
||||
public void OnExitLiquid()
|
||||
private void OnDisable()
|
||||
{
|
||||
if (_onLiquidEntered != null) _onLiquidEntered.OnEventRaised -= OnEnterLiquid;
|
||||
if (_onLiquidExited != null) _onLiquidExited.OnEventRaised -= OnExitLiquid;
|
||||
}
|
||||
|
||||
public void OnEnterLiquid(LiquidEvent evt)
|
||||
{
|
||||
if (evt.LiquidType != nameof(LiquidType.Water)) return;
|
||||
if (_playerStats != null && _playerStats.HasAbility(AbilityType.Swim)) return;
|
||||
_isActive = true;
|
||||
_drownTimer = _config != null ? _config.DrownTime : 3f;
|
||||
}
|
||||
|
||||
public void OnExitLiquid(LiquidEvent evt)
|
||||
{
|
||||
_isActive = false;
|
||||
_drownTimer = _config.DrownTime;
|
||||
_onDrownProgress.Raise(0f);
|
||||
_drownTimer = _config != null ? _config.DrownTime : 3f;
|
||||
_onDrownProgress?.Raise(0f);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_isActive) return;
|
||||
_drownTimer -= Time.deltaTime;
|
||||
_onDrownProgress.Raise(1f - (_drownTimer / _config.DrownTime));
|
||||
float drownTime = _config != null ? _config.DrownTime : 3f;
|
||||
_onDrownProgress?.Raise(1f - (_drownTimer / drownTime));
|
||||
if (_drownTimer <= 0f)
|
||||
{
|
||||
_isActive = false;
|
||||
_onPlayerDrowned.Raise();
|
||||
_onPlayerDrowned?.Raise();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1597,8 +1614,8 @@ public class UnderwaterPostProcessingController : MonoBehaviour
|
||||
[SerializeField] private Volume _underwaterVolume; // 水下专属 Volume(WeightMode)
|
||||
[SerializeField] private float _blendInDuration = 0.3f;
|
||||
[SerializeField] private float _blendOutDuration = 0.3f;
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidEntered; // ⚠️ EVT_LiquidEntered(payload: LiquidZone)
|
||||
[SerializeField] private VoidEventChannelSO _onLiquidExited; // ⚠️ EVT_LiquidExited
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered(payload: LiquidEvent struct)
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited(与 Enter 同类型,保持一致)
|
||||
|
||||
private Coroutine _blendCoroutine;
|
||||
|
||||
@@ -1613,12 +1630,12 @@ public class UnderwaterPostProcessingController : MonoBehaviour
|
||||
_onLiquidExited.OnEventRaised -= OnLiquidExited;
|
||||
}
|
||||
|
||||
private void OnLiquidEntered(LiquidZone zone)
|
||||
private void OnLiquidEntered(LiquidEvent evt)
|
||||
{
|
||||
if (zone.Type != LiquidType.Water) return;
|
||||
if (evt.LiquidType != nameof(LiquidType.Water)) return;
|
||||
BlendVolume(1f, _blendInDuration);
|
||||
}
|
||||
private void OnLiquidExited() => BlendVolume(0f, _blendOutDuration);
|
||||
private void OnLiquidExited(LiquidEvent evt) => BlendVolume(0f, _blendOutDuration);
|
||||
|
||||
private void BlendVolume(float target, float duration)
|
||||
{
|
||||
@@ -1641,7 +1658,7 @@ public class UnderwaterPostProcessingController : MonoBehaviour
|
||||
|
||||
---
|
||||
|
||||
## 4. Week 12:进程模块(护符/工具/技能)
|
||||
## 4. Week 12:进程模块(护符/工具/技能)✅ 完成(2026-05-10)
|
||||
|
||||
**参考文档**:`09_ProgressionModule.md`
|
||||
|
||||
@@ -2475,7 +2492,7 @@ public class HPContainerPickup : MonoBehaviour
|
||||
|
||||
---
|
||||
|
||||
## 5. Week 13:任务与挑战房间
|
||||
## 5. Week 13:任务与挑战房间 ✅ 完成(2026-05-11)
|
||||
|
||||
**参考文档**:`22_QuestChallengeModule.md`
|
||||
|
||||
@@ -3089,7 +3106,7 @@ public class QuestGiver : InteractableNPC
|
||||
|
||||
---
|
||||
|
||||
## 6. Week 14:地图/商店/存档迁移
|
||||
## 6. Week 14:地图/商店/存档迁移 ✅ 完成(P3-5,2026-05-11)
|
||||
|
||||
**参考文档**:`15_MapShopModule.md`
|
||||
|
||||
@@ -3624,6 +3641,58 @@ public static class SaveMigrator
|
||||
|
||||
## 7. 完成标准检查清单
|
||||
|
||||
### Week 10 已完成实现(2026-05-10)
|
||||
|
||||
| 文件 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| `WorldStateRegistry.cs` | ✅ | ScriptableObject,Contains/Mark 系列 API + HasFlag/SetFlag + LoadFromSave |
|
||||
| `InteractableDetector.cs` | ✅ | OverlapCircleAll + FindNearest + InputReaderSO.InteractEvent 绑定 |
|
||||
| `PlayerSpawnPoint.cs` | ✅ | TransitionId + SpawnPosition,Gizmo 绿球标记 |
|
||||
| `RoomTransition.cs` | ✅ | IInteractable,自动触发或按键,广播 `scene|transitionId` 字符串 |
|
||||
| `RoomController.cs` | ✅ | Start 切换 RoomCamera,GetSpawnPoint 查询出生点 |
|
||||
| `HazardZone.cs` | ✅ | 即死/定值伤害,RespawnType 枚举 |
|
||||
| `Collectible.cs` | ✅ | Geo/Item/HPOrb 三类,PlayerStats 直接调用 |
|
||||
| `DestructibleTile.cs` | ✅ | IDamageable,CheckDestroyCondition virtual hook,Start 读档恢复 |
|
||||
| `DirectionalDestructible.cs` | ✅ | AttackSide 枚举 + SourcePosition 方向校验 |
|
||||
| `DirectionalInteractable.cs` | ✅ | 三触发模式 + TriggerSide + OneShot 持久化 |
|
||||
| `MagicWall.cs` | ✅ | Gizmo-only 标记,穿越靠 Layer Matrix |
|
||||
| `SoftTerrain.cs` | ✅ | Marker 组件(无逻辑) |
|
||||
| `PhantomInteractable.cs` | ✅ | 继承 DirectionalInteractable,额外响应 PhantomBody 层 |
|
||||
| `MovingPlatform.cs` | ✅ | LinearAB/WayPoints/TriggeredLinear + Passenger SetParent 方案 |
|
||||
| `CrumblePlatform.cs` | ✅ | Warning/Crumbling/Gone/Respawn 四态协程 + MMF_Player |
|
||||
| `FalseWall.cs` | ✅ | IDamageable,Proximity/AttackOnce/AlwaysOpen 三种揭示方式 |
|
||||
| `BaseGames.World.asmdef` | ✅ | 新增 Input/Combat/Player/Camera/MoreMountains.Tools 引用 |
|
||||
|
||||
### P3-2 补充实现(2026-05-12)
|
||||
|
||||
| 文件 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| `WorldMarkerEventChannelSO.cs` | ✅ | `BaseEventChannelSO<WorldMarker>` 事件频道;命名空间 `BaseGames.World` |
|
||||
| `WorldMarker.cs` | ✅ | 场景导航标记点;`Activate()`/`Deactivate()` 广播事件频道;`WorldMarkerType` 枚举(Objective/NPC/PointOfInterest/Exit/Secret) |
|
||||
| `BreadcrumbTracker.cs` | ✅ | 玩家位置历史追踪;`_recordInterval=2f`/`_maxCrumbs=20`/`_minMoveDistance=1f`;`GetRecentCrumbs(int)` → `IReadOnlyList<Vector2>`(oldest→newest);`Clear()` |
|
||||
| `TutorialManager.cs` | ✅ | 单例 (`Instance`);实现 `ISaveable`;`ShowHint`/`CompleteHint`;进度写入 `SaveData.Tutorial`(非 PlayerPrefs,与架构 12 §1 注解不同) |
|
||||
| `TutorialHintUI.cs` | ✅ | HUD 提示 UI;`Show(text, duration)` + `Hide()`;`AutoHideRoutine` 协程;TMP_Text 标签 |
|
||||
| `ContextualHintTrigger.cs` | ✅ | `[RequireComponent(Collider2D)]`;`_requiresAbility`/`_requiredAbility(AbilityType)` 条件;调用 `LocalizationManager.Get`;首次触发后 `gameObject.SetActive(false)` |
|
||||
| `SaveData.cs` | ✅ | 追加 `TutorialSaveData Tutorial = new()`;新增 `TutorialSaveData` 类(含 `List<string> CompletedHintIds`) |
|
||||
| `BaseGames.Tutorial.asmdef` | ✅ | 引用 Core.Events/Core.Save/World/Player/Localization |
|
||||
|
||||
```
|
||||
☑ InteractableDetector:OverlapCircleAll 检测最近交互物,驱动 UI 提示显示/隐藏(代码完成)
|
||||
☑ WorldStateRegistry:HashSet 持久化状态,LoadFromSave/GetAllFlags 接口完成
|
||||
☑ RoomTransition + RoomController + PlayerSpawnPoint:房间切换框架完成(待 SceneLoader 集成)
|
||||
☑ HazardZone:即死/定值伤害(代码完成,待 Unity 内配置 Layer 和 Tag 验证)
|
||||
☑ Collectible:Geo/Item/HPOrb 拾取(代码完成,待 Unity 内配置 Prefab 验证)
|
||||
☑ DestructibleTile + DirectionalDestructible:IDamageable + 方向校验(代码完成)
|
||||
☑ DirectionalInteractable + PhantomInteractable:三种触发模式 + WorldStateRegistry 持久化
|
||||
☑ MagicWall + SoftTerrain:标记组件(无逻辑)
|
||||
☑ MovingPlatform:三种移动模式 + Passenger SetParent 方案(代码完成)
|
||||
☑ CrumblePlatform:四态协程,MMF_Player 反馈(代码完成)
|
||||
☑ FalseWall:三种揭示条件 + IDamageable(代码完成)
|
||||
□ 场景内端对端验证(待 Unity 编辑器内装配 Prefab 并运行)
|
||||
□ Console 无 Error(Unity 编辑器内编译验证)
|
||||
```
|
||||
|
||||
### Week 11–14 待实施
|
||||
```
|
||||
□ RoomTransition:触发切换 → 淡出 → 加载目标场景 → 玩家在对应 SpawnPoint 出生
|
||||
□ HazardZone:掉入深渊 → 瞬间死亡 → 正常死亡流程
|
||||
@@ -3637,14 +3706,31 @@ public static class SaveMigrator
|
||||
□ FormSkillSO:切换形态 → 对应技能可用 → 释放消耗 SoulPower
|
||||
□ QuestManager:接任务 → 击杀指定敌人 → 进度推进 → 交任务 → 获得奖励
|
||||
□ ChallengeRoom:进入 → 锁门 → 三波敌人依次生成 → 通关 → 奖励 + 开门
|
||||
□ MapPanel:探索新房间后地图格子变亮,已探索持久化(重启后不重置)
|
||||
□ ShopController:购买护符 → Geo 减少 → 护符进入 Inventory → 商店标记已售出
|
||||
☑ MapPanel:探索新房间后地图格子变亮,已探索持久化(MapManager ISaveable 已实现)
|
||||
☑ ShopController:购买护符 → Geo 减少(EVT_ItemPurchased)→ 商店标记已售出(IsUnique 机制)
|
||||
□ 存档迁移:旧版本存档文件加载时无报错,缺失字段填充默认值
|
||||
□ AddressReferenceGraphWindow(菜单 BaseGames/Tools/Asset Reference Graph)无孤儿 key(红色标记)
|
||||
□ MapRoomDataEditor(CustomEditor for MapRoomDataSO):Scene 内拖拽 GridPosition/GridSize 句柄无报错
|
||||
□ Console 无 Error
|
||||
```
|
||||
|
||||
### Week 14 已完成实现(P3-5,地图与商店模块)
|
||||
|
||||
| 文件 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| `MapRoomDataSO.cs` | ✅ | `MapRoomDataSO` + `MapDatabaseSO` + `RoomExitData` + `ExitDirection` |
|
||||
| `MapManager.cs` | ✅ | ISaveable;`[DefaultExecutionOrder(-700)]`;订阅 `EVT_RoomEntered`;`SetMapped` |
|
||||
| `MapPanel.cs` | ✅ | `MapPanel` + `MapRoomCellUI`;OnEnable 重建格子;`EVT_MapUpdated` 增量刷新 |
|
||||
| `MapPlayerTracker.cs` | ✅ | `WorldToCell`(18f/格);LateUpdate 找所在房间;`NormalizedPositionInRoom` |
|
||||
| `MapPin.cs` | ✅ | `MapPinManager` ISaveable(MapPin/PinType 定义在 SaveData.cs 避免循环依赖) |
|
||||
| `ShopItemSO.cs` | ✅ | `ShopItemSO` + `ShopItemType` 枚举;CharmSO 引用 |
|
||||
| `ShopInventorySO.cs` | ✅ | `ShopInventorySO` + `RestockPolicy` 枚举 |
|
||||
| `ShopController.cs` | ✅ | ISaveable;`TryPurchase`;`GetAvailableItems`;`Restock`;`ShopPanel` 存根 |
|
||||
| `ShopNPC.cs` | ✅ | IInteractable;`DialogueEventChannelSO` 触发招呼对话→打开商店 |
|
||||
| `Editor/Map/MapRoomDataEditor.cs` | ✅ | `[CustomEditor(typeof(MapRoomDataSO))]`;Scene 句柄拖拽;居中按钮 |
|
||||
| `SaveData.cs` | ✅ | `MapSaveData`:`ExploredRooms/MappedRooms(List<string>)` + `Pins(List<MapPin>)` |
|
||||
| `BaseGames.World.Map.asmdef` | ✅ | 新增 `BaseGames.Core.Save` + `BaseGames.Core.Events` 引用 |
|
||||
| `BaseGames.World.Shop.asmdef` | ✅ | 新增 `BaseGames.Core.Save` + `BaseGames.Equipment` + `BaseGames.Dialogue` 引用 |
|
||||
| `BaseGames.Editor.asmdef` | ✅ | 新增 `BaseGames.World.Map` 引用(MapRoomDataEditor 需要) |
|
||||
|
||||
> **编辑器工具**:`AddressReferenceGraphWindow`(`Assets/Editor/Assets/AddressReferenceGraphWindow.cs`)扫描所有 `.cs` 文件对 `AddressKeys.X` 的引用,标红孤儿 key(0 引用),标黄单次引用 key,标绿 ≥2 次引用 key,支持导出 CSV(架构 13 §11,P3 优化)。
|
||||
|
||||
**Phase 3 完成后进入 Phase 4。**
|
||||
|
||||
Reference in New Issue
Block a user