geometry-tower-defense-base/docs/LayeredArchitectureDesign.md

668 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 程序集三层拆分方案
最后更新2026-04-30
## 1. 设计目标
将项目拆分为三层,逐步解耦 Unity 依赖,实现核心业务逻辑的可测试性和可移植性:
- **L0Domain**:纯 C# 业务层,引用 GameFramework.dll 作为基础设施,可在独立解决方案中构建
- **L1Infrastructure**:胶水层,连接 L0 与 Unity Runtime 类型
- **L2Presentation**表现层Unity MonoBehaviour、UGuiForm、Entity 实现
---
## 2. GameFramework.dll 复用
项目自带的 `Assets/GameFramework/Libraries/GameFramework.dll` 是 **纯 C# 实现**的 GameFramework 核心库,包含 19 个模块。L0 直接引用此 DLL无需重新实现。
### 2.1 可直接使用的模块
| 模块 | 提供内容 | L0 使用方式 |
|------|---------|-----------|
| **Event** | `EventManager`, `GameEventArgs` | `GameEntry.Event` 替换为 `EventManager` |
| **ObjectPool** | `ObjectPoolManager`, `ObjectBase` | 继承 `ObjectBase`,无需自己实现池 |
| **Fsm** | `FsmManager`, `FsmState`, `FsmState<T>` | 继承 `FsmState<T>` 构建状态机 |
| **ReferencePool** | `ReferencePool` | `ReferencePool.Acquire<T>()` / `Release()` |
| **DataNode** | 树状数据结构 | 直接使用 |
| **Utility** | 通用工具类 | 直接使用 |
| **Config** | 配置管理 | 直接使用 |
| **DataTable** | 表格加载解析 | 数据行类依赖 GameFramework |
### 2.2 需要 Unity 适配的模块
以下模块需要 L1 提供 Unity 特定实现:
| 模块 | 原因 | L1 适配职责 |
|------|------|------------|
| **Resource** | 依赖 Unity Resources/AssetDatabase | 实现 `IResourceManager` |
| **Scene** | 依赖 Unity SceneManager | 实现 `ISceneManager` |
| **Entity** | 依赖 Unity GameObject | 实现 `IEntityManager` |
| **UI** | 依赖 Unity UGUI | 实现 `IUIFormManager` |
| **Sound** | 依赖 Unity Audio | 实现 `ISoundManager` |
### 2.3 复用带来的简化
```
传统方案(自研基础设施)
├── 需要自己实现事件系统
├── 需要自己实现对象池基类
├── 需要自己实现状态机框架
└── 大量基础设施代码
GameFramework.dll 方案
├── 事件 → GameFramework.Event.EventManager
├── 对象池 → GameFramework.ObjectPool
├── 状态机 → GameFramework.Fsm
└── 专注业务逻辑实现
```
---
## 3. 三层职责定义
### L0 - Domain纯 C# 业务层)
- 引用 `GameFramework.dll`,使用其提供的 Event/ObjectPool/Fsm 等基础设施
- 包含所有业务规则、状态机、领域逻辑
-`using UnityEngine`、`using UnityGameFramework.Runtime`
- 通过接口与 L1 通信
- 在独立 .sln 中构建,输出 DLL 导入 Unity
### L1 - Infrastructure胶水层
- 实现 GameFramework 的 Unity 特定接口Resource/Scene/Entity/UI/Sound
- 实现 L0 定义的扩展接口(如 `ICombatEventHandler`
- 持有 L0 服务实例,管理 Unity 生命周期
- 直接依赖 UnityEngine 和 GameFramework.Runtime
### L2 - Presentation表现层
- 所有 `MonoBehaviour`
- View 层UGuiForm 具体实现)
- Entity LogicPlayer、Enemy、Tower 具体实体)
- ECS 组件MovementComponent、ShooterBullet 等)
---
## 4. 程序集映射
### 4.1 L0 程序集
```
GeometryTD.Domain/ ← 引用 GameFramework.dll
├── Definition/
│ ├── Enum/ # 所有枚举类型
│ ├── Constant/ # 常量定义
│ ├── DataStruct/ # 纯数据结构AttackPayload, TowerStatsData 等)
│ └── Tag/
│ ├── Aggregation/ # Tag 汇总服务
│ ├── Generation/ # Tag 生成规则
│ ├── Metadata/ # Tag 定义元数据
│ └── Combat/ # Tag 效果解析
├── GameFramework/ # GameFramework.dll 直接使用
│ └── Event/ # 自定义事件 args继承 GameEventArgs
├── CustomComponent/
│ ├── CombatNode/ # 战斗域
│ │ ├── CombatScheduler # 基于 GameFramework.Fsm
│ │ ├── EnemyManager # 敌人生成、追踪
│ │ ├── CombatRunResourceStore # 战斗资源存储
│ │ └── CombatSettlementCalculator
│ ├── PlayerInventory/ # 背包、交易、组装服务
│ └── InventoryGeneration/ # 掉落、商店、奖励生成
├── UI/
│ ├── Base/
│ │ ├── IUIUseCase.cs
│ │ └── UIContext.cs
│ ├── Combat/
│ │ ├── UseCase/ # CombatSelectFormUseCase, CombatInfoFormUseCase
│ │ ├── RawData/
│ │ └── Context/
│ ├── Game/
│ │ ├── UseCase/ # EventFormUseCase, NodeMapFormUseCase, RepoFormUseCase
│ │ ├── RawData/
│ │ └── Context/
│ └── General/
│ ├── UseCase/
│ ├── RawData/
│ └── Context/
└── Utility/
├── InventoryCloneUtility.cs
├── EnumUtility.cs
└── InventoryRarityRuleService.cs
```
### 4.2 L1 程序集
```
GeometryTD.Infrastructure/
├── GameFramework/ # GameFramework Unity 适配
│ ├── Resource/ # 实现 IResourceManager
│ ├── Scene/ # 实现 ISceneManager
│ ├── Entity/ # 实现 IEntityManager
│ ├── UI/ # 实现 IUIFormManager
│ └── Sound/ # 实现 ISoundManager
├── CustomComponent/
│ ├── CombatNode/
│ │ └── CombatNodeComponent.cs # Unity Component
│ ├── PlayerInventory/
│ │ └── PlayerInventoryComponent.cs
│ ├── InventoryGeneration/
│ │ └── InventoryGenerationComponent.cs
│ ├── EventNodeComponent.cs
│ ├── ShopNodeComponent.cs
│ ├── TagRegistry/
│ │ └── TagRegistryComponent.cs
│ └── BuiltinDataComponent.cs
├── Scene/
│ └── Map/
│ ├── MapTopologyService.cs # Tilemap 扫描
│ ├── TowerPlacementService.cs # 依赖 GameEntry.Entity
│ ├── TowerSelectionPresenter.cs
│ └── MapCombatRuntimeBridge.cs
├── Entity/
│ ├── EntityLogic/
│ │ ├── EntityBase.cs
│ │ ├── CombatSelectInputService.cs
│ │ ├── CombatSelectUseCaseConfigurator.cs
│ │ └── MapEntity.cs
│ ├── EntityData/ # Unity 可序列化
│ │ ├── MapData.cs
│ │ ├── TowerData.cs
│ │ ├── EnemyData.cs
│ │ └── BulletData.cs
│ └── EntityExtension.cs
├── UI/
│ ├── Base/ # Unity 相关基类
│ │ ├── UGuiForm.cs
│ │ ├── UGuiGroupHelper.cs
│ │ ├── UIFormControllerCommonBase.cs
│ │ ├── UIExtension.cs
│ │ └── UIFormControllerBase.cs
│ └── Combat/
│ └── Controller/
├── DataTable/ # GameFramework.DataTable 依赖
│ └── DR*.cs
└── Procedure/ # GameFramework.Procedure
└── ProcedureMain/
```
### 4.3 L2 程序集
```
GeometryTD.Presentation/
├── UI/
│ ├── Combat/
│ │ └── View/
│ ├── Game/
│ │ └── View/
│ ├── General/
│ │ └── View/
│ ├── Templates/
│ └── Common/
├── Entity/
│ └── EntityLogic/
│ ├── Player.cs
│ ├── Enemy.cs
│ ├── TowerEntity.cs
│ ├── BulletEntity.cs
│ └── EnemyTagStatusRuntime.cs
└── Components/
├── MovementComponent.cs
├── ShooterBullet.cs
├── ShooterMuzzleComp.cs
├── TowerController.cs
├── InputComponent.cs
├── BasicBaseComp.cs
└── BasicBearingComp.cs
```
---
## 5. GameFramework 集成方式
### 5.1 事件系统
L0 使用 GameFramework 内置的 `EventManager`,无需自己实现事件系统:
```csharp
// L0: 定义游戏事件,继承 GameFramework.Event.GameEventArgs
public class CombatCoinChangedEventArgs : GameEventArgs
{
public const int EventId = typeof(CombatCoinChangedEventArgs).GetHashCode();
public int CurrentCoin { get; private set; }
public int Delta { get; private set; }
public CombatCoinChangedEventArgs() { }
public CombatCoinChangedEventArgs(int currentCoin, int delta)
{
CurrentCoin = currentCoin;
Delta = delta;
}
}
// L0: 服务中使用
public class CombatRunResourceStore
{
private IEventManager _event;
public CombatRunResourceStore(IEventManager eventManager)
{
_event = eventManager;
}
public void AddCoin(int amount)
{
CurrentCoin += amount;
_event.Fire(this, CombatCoinChangedEventArgs.Create(CurrentCoin, amount));
}
}
```
### 5.2 状态机
L0 使用 GameFramework 的 Fsm 模块:
```csharp
// L0: 战斗状态机基于 GameFramework.Fsm
public interface ICombatFsm { } // 空接口,用于泛型约束
public class CombatScheduler
{
private IFsmManager _fsmManager;
private CombatSchedulerRuntime _runtime;
public CombatScheduler(IFsmManager fsmManager)
{
_fsmManager = fsmManager;
_runtime = new CombatSchedulerRuntime();
}
public void Start()
{
_fsmManager.CreateFsm<ICombatFsm>(this,
new CombatLoadingState(),
new CombatRunningPhaseState(),
new CombatWaitingForPhaseEndState(),
new CombatSettlementState());
}
}
// L0: 具体状态继承 FsmState
public class CombatRunningPhaseState : FsmState<ICombatFsm>
{
protected internal override void OnEnter(ICombatFsm fsmOwner)
{
// 初始化
}
protected internal override void OnUpdate(ICombatFsm fsmOwner, float elapseSeconds)
{
// 每帧更新
}
protected internal override void OnLeave(ICombatFsm fsmOwner, bool isShutdown)
{
// 清理
}
}
```
### 5.3 对象池
L0 使用 GameFramework 的 ObjectPool
```csharp
// L0: 敌人继承 ObjectBase
public class EnemyObject : ObjectBase
{
public int EnemyId { get; private set; }
public int Health { get; private set; }
protected internal override void OnSpawn(bool isRecycle)
{
// 激活时调用
}
protected internal override void OnDespawn(bool isRecycle)
{
// 回收时调用
}
public void Initialize(int enemyId, int health)
{
EnemyId = enemyId;
Health = health;
}
}
// L0: 使用对象池
public class EnemyManager
{
private IObjectPoolManager _poolManager;
public EnemyManager(IObjectPoolManager poolManager)
{
_poolManager = poolManager;
}
public void SpawnEnemy(int enemyId, int health)
{
var pool = _poolManager.GetOrCreateObjectPool<EnemyObject>("EnemyPool");
var enemy = EnemyObject.Create(enemyId, health);
pool.Register(enemy, true);
}
}
```
---
## 6. L1 桥接设计
### 6.1 GameFramework Unity 适配接口
GameFramework.dll 定义了以下接口L1 需要提供 Unity 实现:
```csharp
// GameFramework 定义的接口L0 引用)
namespace GameFramework.Resource
{
public interface IResourceManager
{
void LoadAsset(string assetName, LoadAssetCallbacks callbacks, object userData);
void UnloadAsset(string assetName);
// ...
}
}
// L1: Unity 实现
public class UnityResourceManager : IResourceManager
{
public void LoadAsset(string assetName, LoadAssetCallbacks callbacks, object userData)
{
// 使用 Unity Resources.Load 或 Addressables
}
}
```
### 6.2 L0 服务生命周期管理
```csharp
// L1: Unity Component 持有 L0 服务实例
public class CombatNodeComponent : GameFrameworkComponent
{
private IEventManager _eventManager;
private IObjectPoolManager _poolManager;
private IFsmManager _fsmManager;
// L0 服务
private CombatScheduler _scheduler;
private EnemyManager _enemyManager;
private void Awake()
{
// 初始化 GameFramework Unity 适配器
_eventManager = GameEntry.GetComponent<EventComponent>();
_poolManager = GameEntry.GetComponent<ObjectPoolComponent>();
_fsmManager = GameEntry.GetComponent<FsmComponent>();
// 初始化 L0 服务(注入依赖)
_enemyManager = new EnemyManager(_poolManager);
_scheduler = new CombatScheduler(_fsmManager, _enemyManager);
}
}
```
---
## 7. Unity 类型处理策略
### 7.1 Vector3 / Quaternion / Color
| 类型 | 方案 |
|------|------|
| `Vector3` | 使用 `System.Numerics.Vector3`GameFramework 内部已使用 |
| `Quaternion` | 使用 `System.Numerics.Quaternion` |
| `Color` | 定义纯 C# Color 结构 `{ float r, g, b, a; }` |
### 7.2 [Serializable]
```csharp
// L0: POCO 数据结构
public class TowerStatsData
{
public int[] AttackDamage { get; set; }
public float[] AttackSpeed { get; set; }
}
// L1: Unity 可序列化 DTO
[Serializable]
public class TowerStatsDataDto
{
[SerializeField] private int[] _attackDamage;
[SerializeField] private float[] _attackSpeed;
public TowerStatsData ToDomain() => new()
{
AttackDamage = _attackDamage,
AttackSpeed = _attackSpeed
};
}
```
### 7.3 Sprite 引用
```csharp
// L0: 使用资源路径而非 Sprite 引用
public class TowerSelectItemRawData
{
public string IconPath { get; set; } // "UI/Icons/TowerIcon"
}
// L1: Controller 负责路径到 Sprite 的解析
public class CombatSelectFormController
{
private SpriteCacheComponent _spriteCache;
private TowerSelectItemContext BuildContext(TowerSelectItemRawData raw)
{
return new TowerSelectItemContext
{
Icon = _spriteCache.GetSprite(raw.IconPath)
};
}
}
```
---
## 8. 迁移顺序
### Phase 1: 基础设施搭建
| 任务 | 说明 |
|------|------|
| 创建 L0 项目,引用 GameFramework.dll | 验证基础依赖 |
| 验证 GameFramework Event/Fsm/ObjectPool 可用 | 核心模块连通性测试 |
| 创建 L1 基础结构 | Unity Component 基类、GameFramework 适配器 |
### Phase 2: 核心业务迁移(低风险优先)
| 迁移项 | 说明 | 依赖 |
|--------|------|------|
| `Definition/Enum/*` | 枚举类型 | 无 |
| `Definition/Constant/*` | 常量定义 | 无 |
| `UI/*/RawData/*` | 原始数据 | 无 |
| `UI/*/Context/*` | 上下文 | 无 |
| `Utility/*` | 工具类 | 无 |
### Phase 3: 业务域迁移
| 迁移项 | 说明 | 依赖 |
|--------|------|------|
| `InventoryGeneration/*` | 掉落、商店、奖励 | Phase 1-2 |
| `PlayerInventory/*` | 背包、交易、组装 | Phase 1-2 |
| `UI/*/UseCase/*` | 用例 | Phase 2 + Sprite 路径化 |
| `Definition/Tag/*` | Tag 系统 | Phase 1-2 |
### Phase 4: 战斗域(核心难点)
| 迁移项 | 说明 | 依赖 |
|--------|------|------|
| `CombatNode/CombatScheduler` | 状态机 | GameFramework.Fsm |
| `CombatNode/EnemyManager/*` | 敌人域 | GameFramework.ObjectPool |
| `CombatNode/CombatRunResourceStore` | 资源存储 | GameFramework.Event |
| `CombatNode/CombatSettlementCalculator` | 结算 | Phase 3 |
### Phase 5: 胶水和表现层迁移
| 迁移项 | 说明 |
|--------|------|
| `CustomComponent/*Component` | Unity Component |
| `UI/Base/*` | Controller 基类 |
| `UI/*/Controller/*` | Controller 实现 |
| `UI/*/View/*` | View 实现 |
| `Entity/EntityLogic/*` | Entity 实现 |
---
## 9. 项目文件组织
### 9.1 L0 项目文件
```xml
<!-- GeometryTD.Domain.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<RootNamespace>GeometryTD.Domain</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Reference Include="GameFramework">
<HintPath>..\..\Assets\GameFramework\Libraries\GameFramework.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
```
### 9.2 L1 项目文件
```xml
<!-- GeometryTD.Infrastructure.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GeometryTD.Domain\GeometryTD.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="UnityEngine">
<HintPath>Unity\Editor\Data\Managed\UnityEngine\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityGameFramework.Runtime">
<!-- Unity GameFramework Runtime 引用 -->
</Reference>
</ItemGroup>
</Project>
```
### 9.3 Unity 资产结构
```
Assets/
├── GameFramework/
│ └── Libraries/
│ ├── GameFramework.dll ← L0 直接引用
│ └── GameFramework.xml ← 文档
├── GameMain/
│ ├── L0/ # L0 DLL 输出
│ ├── L1/ # L1 源码或 DLL
│ └── Scripts/
│ └── L2/ # L2 表现层
```
---
## 10. 验收标准
1. **L0 可独立编译**:不包含 UnityEngine.dll、UnityGameFramework.Runtime 引用
2. **GameFramework.dll 正确引用**L0 可使用 Event/ObjectPool/Fsm/ReferencePool
3. **无循环依赖**L2 → L1 → L0单向依赖
4. **接口隔离**L0 与 Unity 的交互通过 L1 适配器
5. **游戏流程完整**:拆分后战斗、商店、组装流程正常运行
---
## 11. 附录GameFramework.dll 模块清单
```
GameFramework.dll 包含以下 19 个模块(纯 C# 实现):
配置与数据
├── Config - 全局配置管理
├── DataNode - 树状数据结点
├── DataTable - 表格数据管理
└── Setting - 键值对存储
核心设施
├── Event - 事件管理EventPool
├── ObjectPool - 对象池ObjectPoolManager
├── ReferencePool - 引用计数池
├── Fsm - 有限状态机
└── Procedure - 流程ProcedureBase
资源管理
├── Resource - 资源加载(需要 Unity 适配器)
├── Scene - 场景管理(需要 Unity 适配器)
├── Entity - 实体管理(需要 Unity 适配器)
├── UI - 界面管理(需要 Unity 适配器)
└── Sound - 声音管理(需要 Unity 适配器)
网络与下载
├── Network - Socket 长连接
├── WebRequest - HTTP 短连接
└── Download - 文件下载
辅助模块
├── Localization - 多语言(需要资源适配器)
├── FileSystem - 虚拟文件系统
├── Debugger - 调试窗口
└── Utility - 通用工具类
```
---
## 12. 附录:当前 Unity 依赖渗透点
以下文件包含 `using UnityEngine``using UnityGameFramework.Runtime`,需要迁移:
| 文件 | Unity 依赖 | 目标层 |
|------|-----------|-------|
| `TowerPlacementService.cs` | `GameEntry.Entity` | L1 |
| `MapTopologyService.cs` | `Tilemap`, `Vector3Int` | L1 |
| `CombatSelectFormUseCase.cs` | `UnityEngine.Sprite` | L0 → 路径化 |
| `TowerStatsData.cs` | `[Serializable]`, `Color` | L0 → POCO + DTO |
| `AttackPayload.cs` | `Vector3` | L0 → System.Numerics |
| `MapEntity.cs` | `MonoBehaviour` | L1 |
| `EnemyEntity.cs` | `Transform` | L2 |
| `GameEntry.Builtin.cs` | `GameFrameworkComponent` | L1 |