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

20 KiB
Raw Permalink Blame History

程序集三层拆分方案

最后更新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 UnityEngineusing 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,无需自己实现事件系统:

// 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.Vector3GameFramework 内部已使用
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. 验收标准

  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 UnityEngineusing 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