20 KiB
20 KiB
程序集三层拆分方案
最后更新:2026-04-30
1. 设计目标
将项目拆分为三层,逐步解耦 Unity 依赖,实现核心业务逻辑的可测试性和可移植性:
- L0(Domain):纯 C# 业务层,引用 GameFramework.dll 作为基础设施,可在独立解决方案中构建
- L1(Infrastructure):胶水层,连接 L0 与 Unity Runtime 类型
- L2(Presentation):表现层,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 Logic(Player、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,无需自己实现事件系统:
// 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 模块:
// 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:
// 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 实现:
// 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 服务生命周期管理
// 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]
// 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 引用
// 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 项目文件
<!-- 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 项目文件
<!-- 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. 验收标准
- L0 可独立编译:不包含 UnityEngine.dll、UnityGameFramework.Runtime 引用
- GameFramework.dll 正确引用:L0 可使用 Event/ObjectPool/Fsm/ReferencePool
- 无循环依赖:L2 → L1 → L0,单向依赖
- 接口隔离:L0 与 Unity 的交互通过 L1 适配器
- 游戏流程完整:拆分后战斗、商店、组装流程正常运行
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 |