跳转至

Unity C# 代码设计内功:从架构思维到实战经验

设计概述

本文档深入探讨 Unity 中 C# 代码设计的核心理念和实践经验,重点关注代码架构的内功修炼,包括数据容器设计、接口驱动开发、组件化架构等关键方面。通过系统性的设计原则和实战案例,帮助开发者构建高质量、可维护的 Unity 项目。

核心设计理念

数据与行为分离原则

在 Unity 开发中,一个类应该明确其主要职责是作为数据容器还是行为载体。这种分离带来的好处包括:

设计模式 职责定义 优势 适用场景
数据容器类 主要存储状态数据,最小化方法数量 序列化友好、易于调试、数据流清晰 配置数据、游戏状态、持久化对象
行为载体类 主要包含业务逻辑,通过接口暴露能力 职责清晰、易于测试、解耦合度高 系统控制器、服务类、管理器
混合型类 数据与行为并重,通过设计平衡两者 使用便捷、适合小型项目 简单组件、工具类

接口驱动的架构设计

接口在 Unity 开发中扮演着架构契约的重要角色,通过接口可以快速理解类的能力而无需深入实现细节。

接口设计的核心价值

graph TD
    A[接口契约] --> B[能力发现]
    A --> C[依赖解耦]
    A --> D[测试友好]
    A --> E[扩展性强]

    B --> F[快速了解类的职责]
    C --> G[降低模块间耦合]
    D --> H[便于单元测试和模拟]
    E --> I[支持多种实现方式]

接口分层策略

Unity 项目中的接口设计应该遵循分层架构:

接口层级 抽象级别 设计目标 示例
核心能力接口 高抽象 定义基础行为契约 IMoveable, IDamageable, IInteractable
系统功能接口 中抽象 定义子系统职责 IInventorySystem, ISaveSystem, IAudioManager
具体实现接口 低抽象 定义特定实现细节 IWeaponController, IPlayerInput, IEnemyAI

Unity 组件化架构设计

组件化的核心思想

Unity 的 Component 系统天然支持组件化开发,应该充分利用这一特性构建松耦合的架构。

主控制器模式

每个游戏对象应该有一个主要的控制组件,负责协调其他功能组件:

graph TD
    A[主控制器组件] --> B[健康系统组件]
    A --> C[移动系统组件] 
    A --> D[武器系统组件]
    A --> E[音效系统组件]
    A --> F[动画系统组件]

    A --> G[事件协调]
    A --> H[状态管理]
    A --> I[组件通信]

组件职责分工表

组件类型 职责范围 设计特点 通信方式
主控制器 组件协调、状态管理、事件分发 轻量级、接口丰富 UnityEvent、接口调用
功能组件 单一功能实现、状态维护 高内聚、低耦合 事件通知、直接调用
数据组件 配置存储、状态持久化 序列化友好、只读属性 属性访问、配置注入
服务组件 全局服务、跨对象通信 单例模式、生命周期管理 服务定位、依赖注入

组件间通信策略

Unity 组件间通信应该遵循清晰的层次结构:

通信方式优先级

  1. 接口调用(推荐)- 强类型、编译时检查
  2. UnityEvent(适中)- 松耦合、Inspector 可配置
  3. 事件系统(谨慎)- 全局通信、需要良好的事件管理
  4. 静态引用(避免)- 紧耦合、难以测试

SOLID 原则在 Unity 中的实践

单一职责原则(SRP)在组件设计中的应用

组件职责划分矩阵

功能领域 组件名称 核心职责 避免职责
生命值管理 HealthComponent 血量计算、伤害处理、死亡状态 UI 更新、音效播放、动画控制
移动控制 MovementComponent 位置变换、速度控制、物理交互 输入处理、AI 决策、动画同步
武器系统 WeaponComponent 武器逻辑、射击机制、弹药管理 伤害计算、目标搜索、特效播放
输入处理 InputComponent 输入采集、命令转换、输入状态 移动执行、技能释放、界面操作

开闭原则(OCP)在扩展性设计中的体现

策略模式的游戏应用

通过接口和策略模式实现对扩展开放、对修改封闭:

classDiagram
    class IWeaponStrategy {
        +Fire(firePoint, bulletPrefab)
        +CanFire() bool
        +GetDamage() float
    }

    class WeaponSystem {
        -IWeaponStrategy currentWeapon
        +EquipWeapon(IWeaponStrategy)
        +Fire()
    }

    class PistolStrategy {
        +Fire()
        +CanFire()
        +GetDamage()
    }

    class RifleStrategy {
        +Fire()
        +CanFire()
        +GetDamage()
    }

    class ShotgunStrategy {
        +Fire()
        +CanFire()
        +GetDamage()
    }

    IWeaponStrategy <|-- PistolStrategy
    IWeaponStrategy <|-- RifleStrategy
    IWeaponStrategy <|-- ShotgunStrategy
    WeaponSystem --> IWeaponStrategy

依赖倒置原则(DIP)在服务架构中的实现

服务定位器模式

通过抽象接口和服务容器实现依赖倒置:

graph TD
    A[GameManager<br/>高层模块] --> B[IDataStorage<br/>抽象接口]
    A --> C[ILogger<br/>抽象接口]
    A --> D[IAudioManager<br/>抽象接口]

    B --> E[FileDataStorage<br/>具体实现]
    B --> F[CloudDataStorage<br/>具体实现]

    C --> G[UnityLogger<br/>具体实现]
    C --> H[FileLogger<br/>具体实现]

    D --> I[UnityAudioManager<br/>具体实现]
    D --> J[FMODAudioManager<br/>具体实现]

数据驱动的架构设计

ScriptableObject 作为数据容器

数据容器设计原则

  1. 纯数据存储 - 最小化方法,专注于数据序列化
  2. 配置驱动 - 通过配置文件控制游戏行为
  3. 版本兼容 - 考虑数据结构的向后兼容性
  4. 类型安全 - 使用强类型而非字符串键值

数据容器分类策略

数据类型 设计模式 序列化方式 使用场景
配置数据 ScriptableObject Unity 原生序列化 游戏平衡性参数、系统配置
状态数据 普通类 + [Serializable] JsonUtility 或第三方 存档数据、运行时状态
临时数据 结构体或简单类 内存存储 帧间传递、计算缓存
引用数据 资源引用 + 配置 AssetReference 预制体配置、资源管理

配置与逻辑分离

数据驱动的武器系统设计

graph TB
    A[WeaponConfigSO<br/>武器配置数据] --> B[WeaponController<br/>武器逻辑控制]
    C[BulletConfigSO<br/>子弹配置数据] --> D[BulletBehaviour<br/>子弹行为逻辑]
    E[AudioConfigSO<br/>音效配置数据] --> F[AudioManager<br/>音效管理器]

    B --> G[IWeapon<br/>武器接口]
    D --> H[IBullet<br/>子弹接口]
    F --> I[IAudioSource<br/>音频接口]

事件驱动的通信架构

事件系统的层次设计

事件分类与应用场景

事件类型 作用域 生命周期 适用场景
本地事件 组件内部 组件生命周期 状态变化通知、内部逻辑处理
对象事件 GameObject 范围 对象生命周期 组件间通信、功能协调
系统事件 场景或全局 场景或应用生命周期 系统级通知、跨对象通信
业务事件 游戏逻辑 游戏会话 游戏机制、业务流程

事件命名和组织规范

graph TD
    A[事件命名空间] --> B[系统前缀]
    A --> C[动作描述]
    A --> D[时态标识]

    B --> E[Player<br/>玩家系统]
    B --> F[Weapon<br/>武器系统]
    B --> G[UI<br/>界面系统]

    C --> H[Health<br/>生命相关]
    C --> I[Level<br/>等级相关]
    C --> J[Inventory<br/>道具相关]

    D --> K[Changed<br/>已变化]
    D --> L[ing<br/>正在进行]
    D --> M[Requested<br/>请求状态]

性能优化的设计考量

对象池模式在 Unity 中的应用

池化策略设计

对象类型 池化方式 池大小策略 生命周期管理
频繁创建对象 专用对象池 动态扩展 引用计数
相似对象族 通用对象池 固定大小 时间过期
大型对象 懒加载池 小容量 主动回收
临时对象 栈式池 预分配 作用域回收

内存管理和垃圾回收优化

GC 友好的代码设计原则

  1. 减少装箱拆箱 - 使用泛型而非 object 类型
  2. 避免频繁字符串操作 - 使用 StringBuilder 或对象池
  3. 缓存频繁计算结果 - 避免每帧重复计算
  4. 使用结构体存储简单数据 - 减少堆内存分配
  5. 谨慎使用 LINQ - 在性能关键路径避免使用

测试驱动的设计方法

可测试性设计原则

测试友好的架构特征

graph TD
    A[可测试架构] --> B[依赖注入]
    A --> C[接口抽象]
    A --> D[纯函数设计]
    A --> E[状态隔离]

    B --> F[模拟依赖]
    C --> G[契约测试]
    D --> H[单元测试]
    E --> I[集成测试]

测试分层策略

测试层级 测试对象 测试工具 测试重点
单元测试 单个类或方法 NUnit + NSubstitute 逻辑正确性、边界条件
组件测试 Unity 组件 Unity Test Framework 组件交互、生命周期
集成测试 系统模块 自定义测试框架 模块协作、数据流
端到端测试 完整功能 自动化测试工具 用户体验、性能表现

代码组织和模块化

命名空间和程序集设计

模块划分策略

graph TD
    A[项目根命名空间] --> B[Core<br/>核心模块]
    A --> C[Systems<br/>系统模块]
    A --> D[Components<br/>组件模块]
    A --> E[Data<br/>数据模块]
    A --> F[Utils<br/>工具模块]

    B --> G[Interfaces<br/>核心接口]
    B --> H[Base<br/>基础类]
    B --> I[Constants<br/>常量定义]

    C --> J[Audio<br/>音频系统]
    C --> K[Input<br/>输入系统]
    C --> L[Save<br/>存档系统]

文件夹结构和代码组织

推荐的项目结构

目录层级 组织原则 包含内容 命名规范
功能模块 按业务功能划分 相关的类、接口、配置 业务名称 + 模块类型
技术层次 按技术职责划分 相同抽象级别的代码 技术类型 + 功能描述
生命周期 按使用阶段划分 相同生命周期的资源 阶段名称 + 资源类型
依赖关系 按依赖方向划分 低耦合的模块 依赖层级 + 功能名称

版本控制和代码维护

重构策略和时机

重构决策矩阵

重构类型 触发条件 重构范围 风险评估
结构重构 架构腐化、性能问题 模块级别 高风险、需要充分测试
功能重构 需求变更、设计缺陷 功能级别 中风险、影响相关功能
代码重构 代码异味、可读性差 类或方法级别 低风险、局部改进
性能重构 性能瓶颈、资源浪费 算法或数据结构 中风险、需要性能测试

代码质量监控

质量指标体系

graph TD
    A[代码质量] --> B[可读性指标]
    A --> C[可维护性指标]
    A --> D[可测试性指标]
    A --> E[性能指标]

    B --> F[代码复杂度]
    B --> G[命名规范]
    B --> H[注释质量]

    C --> I[耦合度]
    C --> J[内聚度]
    C --> K[重复代码]

    D --> L[测试覆盖率]
    D --> M[Mock 友好度]
    D --> N[依赖注入率]

    E --> O[内存使用]
    E --> P[CPU 占用]
    E --> Q[GC 压力]

QFramework 架构设计案例分析

QFramework 的核心设计理念

QFramework 是一个优秀的 Unity 架构框架,其设计充分体现了本文档所述的各项设计原则。通过分析 QFramework 的架构设计,可以更好地理解 Unity 中 C# 代码设计的最佳实践。

QFramework 四层架构模型

QFramework 采用了清晰的分层架构,完美诠释了职责分离和依赖管理的重要性:

graph TD
    A[IController 表现层] --> B[ISystem 系统层]
    A --> C[IModel 数据层]
    B --> C
    B --> D[IUtility 工具层]
    C --> D

    E[Command/Query] --> B
    E --> C

    F[Event/BindableProperty] --> A

    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#e8f5e8
    style D fill:#fff3e0
层级 职责 依赖关系 通信方式
IController (表现层) 接收输入、状态表现、UI 控制 可获取 System、Model 发送 Command/Query,监听 Event
ISystem (系统层) 业务逻辑、跨 Controller 共享逻辑 可获取 System、Model、Utility 监听/发送 Event
IModel (数据层) 数据存储、数据操作 可获取 Utility 发送 Event
IUtility (工具层) 基础设施、第三方封装 无依赖 纯工具方法

QFramework 中的 SOLID 原则实践

单一职责原则的体现

QFramework 通过分层设计确保每个层级都有明确的职责:

// ✅ 数据层:只负责数据管理
public interface ICounterModel : IModel
{
    BindableProperty<int> Count { get; }
    void IncrementCount();
    void DecrementCount();
}

// ✅ 系统层:只负责业务逻辑
public interface ICounterSystem : ISystem
{
    void ProcessCounterLogic();
    bool CanIncrement();
}

// ✅ 表现层:只负责 UI 表现
public class CounterController : MonoBehaviour, IController
{
    [SerializeField] private Button incrementBtn;
    [SerializeField] private Button decrementBtn;
    [SerializeField] private Text countText;

    private ICounterModel counterModel;

    void Start()
    {
        counterModel = this.GetModel<ICounterModel>();

        // 数据绑定
        counterModel.Count.RegisterWithInitValue(OnCountChanged);

        // 事件绑定
        incrementBtn.onClick.AddListener(() => 
        {
            this.SendCommand<IncrementCountCommand>();
        });
    }

    void OnCountChanged(int newCount)
    {
        countText.text = newCount.ToString();
    }

    public IArchitecture GetArchitecture() => CounterApp.Interface;
}

开闭原则的实现

QFramework 通过接口和 Command 模式实现对扩展开放、对修改封闭:

// ✅ Command 模式:新增功能无需修改现有代码
public class IncrementCountCommand : AbstractCommand
{
    protected override void OnExecute()
    {
        var model = this.GetModel<ICounterModel>();
        var system = this.GetSystem<ICounterSystem>();

        if (system.CanIncrement())
        {
            model.IncrementCount();
        }
    }
}

// 添加新功能:批量增加
public class BatchIncrementCommand : AbstractCommand
{
    private int amount;

    public BatchIncrementCommand(int amount)
    {
        this.amount = amount;
    }

    protected override void OnExecute()
    {
        for (int i = 0; i < amount; i++)
        {
            this.SendCommand<IncrementCountCommand>();
        }
    }
}

依赖倒置原则的应用

QFramework 通过 Architecture 模式和接口实现依赖倒置:

// ✅ Architecture 作为依赖注入容器
public class CounterApp : Architecture<CounterApp>
{
    protected override void Init()
    {
        // 注册 Model
        this.RegisterModel<ICounterModel>(new CounterModel());

        // 注册 System
        this.RegisterSystem<ICounterSystem>(new CounterSystem());

        // 注册 Utility
        this.RegisterUtility<IStorageUtility>(new PlayerPrefsStorage());
    }
}

// ✅ 高层模块不依赖具体实现
public class CounterModel : AbstractModel, ICounterModel
{
    public BindableProperty<int> Count { get; private set; }

    protected override void OnInit()
    {
        var storage = this.GetUtility<IStorageUtility>();
        var savedCount = storage.LoadInt("counter", 0);
        Count = new BindableProperty<int>(savedCount);

        Count.Register(count => 
        {
            storage.SaveInt("counter", count);
        });
    }

    public void IncrementCount()
    {
        Count.Value++;
        this.SendEvent<CountChangedEvent>(new CountChangedEvent(Count.Value));
    }
}

QFramework 的事件驱动设计

类型安全的事件系统

QFramework 提供了类型安全的事件系统,避免了字符串事件的弊端:

// ✅ 类型安全的事件定义
public struct CountChangedEvent
{
    public int NewCount { get; }

    public CountChangedEvent(int newCount)
    {
        NewCount = newCount;
    }
}

// ✅ 事件的发送和监听
public class CounterModel : AbstractModel, ICounterModel
{
    public void IncrementCount()
    {
        Count.Value++;
        // 发送强类型事件
        this.SendEvent<CountChangedEvent>(new CountChangedEvent(Count.Value));
    }
}

public class AchievementSystem : AbstractSystem, IAchievementSystem
{
    protected override void OnInit()
    {
        // 监听强类型事件
        this.RegisterEvent<CountChangedEvent>(OnCountChanged);
    }

    private void OnCountChanged(CountChangedEvent e)
    {
        if (e.NewCount >= 100)
        {
            UnlockAchievement("Master Counter");
        }
    }
}

BindableProperty 的数据绑定

QFramework 的 BindableProperty 提供了响应式的数据绑定机制:

// ✅ 响应式数据绑定
public class PlayerHealthUI : MonoBehaviour, IController
{
    [SerializeField] private Slider healthSlider;
    [SerializeField] private Text healthText;

    private IPlayerModel playerModel;

    void Start()
    {
        playerModel = this.GetModel<IPlayerModel>();

        // 数据绑定:自动同步 UI
        playerModel.Health.RegisterWithInitValue(health => 
        {
            healthSlider.value = health / playerModel.MaxHealth.Value;
            healthText.text = $"{health}/{playerModel.MaxHealth.Value}";
        }).UnRegisterWhenGameObjectDestroyed(gameObject);

        // 多个属性组合绑定
        playerModel.Health.CombineLatest(playerModel.MaxHealth, (h, max) => 
        {
            return new { Health = h, MaxHealth = max };
        }).Register(data => 
        {
            healthSlider.value = (float)data.Health / data.MaxHealth;
            healthText.text = $"{data.Health}/{data.MaxHealth}";
        }).UnRegisterWhenGameObjectDestroyed(gameObject);
    }

    public IArchitecture GetArchitecture() => GameApp.Interface;
}

QFramework 模块化设计实践

可插拔的模块系统

QFramework 支持模块化的系统设计,每个系统都可以独立开发和测试:

// ✅ 模块化的系统设计
public interface IInventorySystem : ISystem
{
    void AddItem(string itemId, int count);
    void RemoveItem(string itemId, int count);
    int GetItemCount(string itemId);
    event System.Action<string, int> OnItemAdded;
    event System.Action<string, int> OnItemRemoved;
}

public class InventorySystem : AbstractSystem, IInventorySystem
{
    private Dictionary<string, int> items = new Dictionary<string, int>();

    public event System.Action<string, int> OnItemAdded;
    public event System.Action<string, int> OnItemRemoved;

    protected override void OnInit()
    {
        // 从存储中加载物品数据
        var storage = this.GetUtility<IStorageUtility>();
        LoadItemsFromStorage(storage);
    }

    public void AddItem(string itemId, int count)
    {
        if (!items.ContainsKey(itemId))
            items[itemId] = 0;

        items[itemId] += count;
        OnItemAdded?.Invoke(itemId, count);

        // 发送事件给其他系统
        this.SendEvent<ItemAddedEvent>(new ItemAddedEvent(itemId, count));
    }

    // ... 其他方法实现
}

// ✅ 系统间的协作
public class ShopSystem : AbstractSystem, IShopSystem
{
    protected override void OnInit()
    {
        // 监听库存变化
        this.RegisterEvent<ItemAddedEvent>(OnItemAdded);
    }

    private void OnItemAdded(ItemAddedEvent e)
    {
        // 检查是否解锁新商品
        CheckUnlockNewItems(e.ItemId);
    }

    public bool PurchaseItem(string itemId, int price)
    {
        var playerModel = this.GetModel<IPlayerModel>();
        var inventorySystem = this.GetSystem<IInventorySystem>();

        if (playerModel.Coins.Value >= price)
        {
            // 通过 Command 执行购买逻辑
            this.SendCommand<PurchaseItemCommand>(new PurchaseItemCommand(itemId, price));
            return true;
        }

        return false;
    }
}

QFramework 设计模式的应用

Command 模式的深度应用

QFramework 的 Command 不仅仅是简单的命令模式,还支持撤销、重做等高级功能:

// ✅ 支持撤销的 Command
public interface IUndoableCommand : ICommand
{
    void Undo();
    bool CanUndo { get; }
}

public class MovePlayerCommand : AbstractCommand, IUndoableCommand
{
    private Vector3 fromPosition;
    private Vector3 toPosition;
    private Transform playerTransform;

    public bool CanUndo => true;

    public MovePlayerCommand(Vector3 to)
    {
        toPosition = to;
    }

    protected override void OnExecute()
    {
        var playerModel = this.GetModel<IPlayerModel>();
        playerTransform = playerModel.PlayerTransform;
        fromPosition = playerTransform.position;

        playerTransform.position = toPosition;
        playerModel.Position.Value = toPosition;
    }

    public void Undo()
    {
        if (playerTransform != null)
        {
            playerTransform.position = fromPosition;
            var playerModel = this.GetModel<IPlayerModel>();
            playerModel.Position.Value = fromPosition;
        }
    }
}

// ✅ Command 历史管理
public class CommandHistory : IUtility
{
    private Stack<IUndoableCommand> undoStack = new Stack<IUndoableCommand>();
    private Stack<IUndoableCommand> redoStack = new Stack<IUndoableCommand>();

    public void ExecuteCommand(IUndoableCommand command)
    {
        command.Execute();
        undoStack.Push(command);
        redoStack.Clear(); // 执行新命令时清空重做栈
    }

    public bool CanUndo => undoStack.Count > 0;
    public bool CanRedo => redoStack.Count > 0;

    public void Undo()
    {
        if (CanUndo)
        {
            var command = undoStack.Pop();
            command.Undo();
            redoStack.Push(command);
        }
    }

    public void Redo()
    {
        if (CanRedo)
        {
            var command = redoStack.Pop();
            command.Execute();
            undoStack.Push(command);
        }
    }
}

组合模式在 QFramework 中的应用

QFramework 支持 Command 的组合,可以构建复杂的命令序列:

// ✅ 复合 Command
public class CompositeCommand : AbstractCommand
{
    private List<ICommand> commands = new List<ICommand>();

    public CompositeCommand Add(ICommand command)
    {
        commands.Add(command);
        return this;
    }

    protected override void OnExecute()
    {
        foreach (var command in commands)
        {
            command.Execute();
        }
    }
}

// 使用示例:玩家升级的复合操作
public class PlayerLevelUpCommand : AbstractCommand
{
    protected override void OnExecute()
    {
        var compositeCommand = new CompositeCommand()
            .Add(new IncreaseLevelCommand())
            .Add(new AddAttributePointsCommand(5))
            .Add(new PlayLevelUpEffectCommand())
            .Add(new SavePlayerDataCommand());

        compositeCommand.Execute();
    }
}

QFramework 的性能优化设计

对象池在 QFramework 中的应用

QFramework 内置了对象池机制,减少 GC 压力:

// ✅ QFramework 的对象池设计
public class PoolableCommand : AbstractCommand, IPoolable
{
    private bool isRecycled = false;

    public bool IsRecycled { get => isRecycled; set => isRecycled = value; }

    protected override void OnExecute()
    {
        // 执行命令逻辑
        DoExecute();

        // 自动回收到对象池
        this.Recycle2Cache();
    }

    protected virtual void DoExecute() { }

    public void OnRecycled()
    {
        // 重置状态
        ResetState();
    }

    protected virtual void ResetState() { }
}

// 使用对象池的 Command
public class DamageCommand : PoolableCommand
{
    private GameObject target;
    private float damage;

    public static DamageCommand Allocate(GameObject target, float damage)
    {
        var command = SafeObjectPool<DamageCommand>.Instance.Allocate();
        command.target = target;
        command.damage = damage;
        return command;
    }

    protected override void DoExecute()
    {
        var health = target.GetComponent<HealthComponent>();
        health?.TakeDamage(damage);
    }

    protected override void ResetState()
    {
        target = null;
        damage = 0;
    }
}

实践建议和经验总结

渐进式架构演进

QFramework 渐进式引入策略

QFramework 的一个突出优势是支持渐进式引入,不需要一次性重构整个项目:

引入阶段 引入内容 改动成本 获得效益
第一阶段 BindableProperty + 事件系统 数据绑定、响应式 UI
第二阶段 IModel + IController 数据层分离、架构清晰
第三阶段 Command 模式 交互逻辑解耦、可撤销操作
第四阶段 ISystem + 全套架构 完整架构体系、模块化开发
// ✅ 阶段一:只使用 BindableProperty
public class SimpleCounterController : MonoBehaviour
{
    [SerializeField] private Button incrementBtn;
    [SerializeField] private Text countText;

    // 直接使用 BindableProperty,无需架构
    private BindableProperty<int> count = new BindableProperty<int>(0);

    void Start()
    {
        // 数据绑定
        count.RegisterWithInitValue(value => 
        {
            countText.text = value.ToString();
        });

        incrementBtn.onClick.AddListener(() => 
        {
            count.Value++;
        });
    }
}

// ✅ 阶段二:引入 Model 和 Controller
public class CounterModel
{
    public BindableProperty<int> Count { get; } = new BindableProperty<int>(0);

    public void Increment() => Count.Value++;
    public void Decrement() => Count.Value--;
}

public class CounterController : MonoBehaviour
{
    [SerializeField] private Button incrementBtn;
    [SerializeField] private Button decrementBtn;
    [SerializeField] private Text countText;

    private CounterModel model;

    void Start()
    {
        model = new CounterModel();

        model.Count.RegisterWithInitValue(OnCountChanged);

        incrementBtn.onClick.AddListener(model.Increment);
        decrementBtn.onClick.AddListener(model.Decrement);
    }

    void OnCountChanged(int newCount)
    {
        countText.text = newCount.ToString();
    }
}

QFramework 在大型项目中的应用案例

复杂游戏系统架构设计

以一个 RPG 游戏为例,展示 QFramework 如何支持复杂的游戏系统:

graph TD
    A[RPGGameApp<br/>游戏架构] --> B[IPlayerModel<br/>玩家数据]
    A --> C[IInventoryModel<br/>背包数据]
    A --> D[IQuestModel<br/>任务数据]

    A --> E[IBattleSystem<br/>战斗系统]
    A --> F[IQuestSystem<br/>任务系统]
    A --> G[IAchievementSystem<br/>成就系统]

    A --> H[IGameplayController<br/>游戏控制]
    A --> I[IUIController<br/>界面控制]
    A --> J[IInputController<br/>输入控制]
// ✅ RPG 游戏的模块化架构
public class RPGGameApp : Architecture<RPGGameApp>
{
    protected override void Init()
    {
        // 数据层
        this.RegisterModel<IPlayerModel>(new PlayerModel());
        this.RegisterModel<IInventoryModel>(new InventoryModel());
        this.RegisterModel<IQuestModel>(new QuestModel());
        this.RegisterModel<ISkillModel>(new SkillModel());

        // 系统层
        this.RegisterSystem<IBattleSystem>(new BattleSystem());
        this.RegisterSystem<IQuestSystem>(new QuestSystem());
        this.RegisterSystem<IAchievementSystem>(new AchievementSystem());
        this.RegisterSystem<ISaveSystem>(new SaveSystem());

        // 工具层
        this.RegisterUtility<IStorageUtility>(new JsonStorageUtility());
        this.RegisterUtility<ITimeUtility>(new UnityTimeUtility());
        this.RegisterUtility<IRandomUtility>(new SystemRandomUtility());
    }
}

// ✅ 系统间的协作示例:战斗系统
public class BattleSystem : AbstractSystem, IBattleSystem
{
    private IPlayerModel playerModel;
    private IInventoryModel inventoryModel;
    private IQuestSystem questSystem;

    protected override void OnInit()
    {
        playerModel = this.GetModel<IPlayerModel>();
        inventoryModel = this.GetModel<IInventoryModel>();
        questSystem = this.GetSystem<IQuestSystem>();

        // 监听敌人死亡事件
        this.RegisterEvent<EnemyDefeatedEvent>(OnEnemyDefeated);
    }

    public void AttackEnemy(EnemyData enemy)
    {
        var damage = CalculateDamage(playerModel, enemy);

        // 执行攻击命令
        this.SendCommand<DealDamageCommand>(new DealDamageCommand(enemy, damage));
    }

    private void OnEnemyDefeated(EnemyDefeatedEvent e)
    {
        // 获得经验值
        var expGained = e.Enemy.ExperienceReward;
        this.SendCommand<GainExperienceCommand>(new GainExperienceCommand(expGained));

        // 获得战利品
        var loot = GenerateLoot(e.Enemy);
        foreach (var item in loot)
        {
            this.SendCommand<AddItemCommand>(new AddItemCommand(item.Id, item.Quantity));
        }

        // 通知任务系统
        questSystem.OnEnemyKilled(e.Enemy.Type);
    }

    private float CalculateDamage(IPlayerModel player, EnemyData enemy)
    {
        var baseDamage = player.Attack.Value;
        var weaponDamage = GetEquippedWeaponDamage();
        var skillMultiplier = GetSkillMultiplier();

        return (baseDamage + weaponDamage) * skillMultiplier;
    }
}

复杂 UI 系统的架构设计

QFramework 在 UI 系统中的应用展示了其在复杂界面管理中的优势:

// ✅ 数据驱动的 UI 设计
public class InventoryPanel : UIPanel, IController
{
    [Header("UI 引用")]
    [SerializeField] private Transform itemContainer;
    [SerializeField] private InventoryItemView itemPrefab;
    [SerializeField] private Button sortButton;
    [SerializeField] private Text capacityText;

    private IInventoryModel inventoryModel;
    private List<InventoryItemView> itemViews = new List<InventoryItemView>();

    void Start()
    {
        inventoryModel = this.GetModel<IInventoryModel>();

        // 监听数据变化
        inventoryModel.Items.RegisterWithInitValue(OnItemsChanged)
            .UnRegisterWhenGameObjectDestroyed(gameObject);

        inventoryModel.Capacity.RegisterWithInitValue(OnCapacityChanged)
            .UnRegisterWhenGameObjectDestroyed(gameObject);

        // UI 事件绑定
        sortButton.onClick.AddListener(() => 
        {
            this.SendCommand<SortInventoryCommand>();
        });

        // 监听物品变化事件
        this.RegisterEvent<ItemUsedEvent>(OnItemUsed);
    }

    private void OnItemsChanged(List<ItemData> items)
    {
        // 清理旧的 UI
        foreach (var view in itemViews)
        {
            if (view != null)
                Destroy(view.gameObject);
        }
        itemViews.Clear();

        // 创建新的 UI
        foreach (var item in items)
        {
            var itemView = Instantiate(itemPrefab, itemContainer);
            itemView.SetData(item);
            itemView.OnItemClicked += (clickedItem) => 
            {
                this.SendCommand<UseItemCommand>(new UseItemCommand(clickedItem.Id));
            };
            itemViews.Add(itemView);
        }
    }

    private void OnCapacityChanged(int capacity)
    {
        var currentCount = inventoryModel.Items.Value.Count;
        capacityText.text = $"{currentCount}/{capacity}";

        // 容量警告
        if (currentCount >= capacity * 0.9f)
        {
            capacityText.color = Color.red;
        }
        else if (currentCount >= capacity * 0.7f)
        {
            capacityText.color = Color.yellow;
        }
        else
        {
            capacityText.color = Color.white;
        }
    }

    private void OnItemUsed(ItemUsedEvent e)
    {
        // 播放使用物品的特效
        PlayItemUseEffect(e.ItemId);
    }

    public IArchitecture GetArchitecture() => RPGGameApp.Interface;
}

// ✅ 可复用的物品视图组件
public class InventoryItemView : MonoBehaviour
{
    [SerializeField] private Image iconImage;
    [SerializeField] private Text nameText;
    [SerializeField] private Text quantityText;
    [SerializeField] private Button useButton;

    public event System.Action<ItemData> OnItemClicked;

    private ItemData itemData;

    void Start()
    {
        useButton.onClick.AddListener(() => 
        {
            OnItemClicked?.Invoke(itemData);
        });
    }

    public void SetData(ItemData data)
    {
        itemData = data;
        iconImage.sprite = data.Icon;
        nameText.text = data.Name;
        quantityText.text = data.Quantity > 1 ? data.Quantity.ToString() : "";

        // 根据物品类型设置不同的显示状态
        useButton.interactable = data.IsUsable;
    }
}

QFramework 的性能优化最佳实践

事件系统的性能优化

QFramework 的事件系统在大量事件监听和发送时的性能优化:

// ✅ 优化的事件处理
public class OptimizedEventSystem : MonoBehaviour
{
    // 使用对象池减少 GC
    private static readonly ObjectPool<List<System.Action>> ActionListPool = 
        new ObjectPool<List<System.Action>>(() => new List<System.Action>(), null, l => l.Clear());

    void Start()
    {
        // 批量事件处理
        var actions = ActionListPool.Get();

        // 收集所有需要执行的事件
        CollectPendingEvents(actions);

        // 批量执行
        foreach (var action in actions)
        {
            action?.Invoke();
        }

        // 回收对象
        ActionListPool.Release(actions);
    }

    // ✅ 按需加载的事件监听
    private readonly Dictionary<System.Type, bool> eventSubscriptions = new Dictionary<System.Type, bool>();

    private void RegisterEventOnDemand<T>(System.Action<T> handler) where T : struct
    {
        var eventType = typeof(T);

        if (!eventSubscriptions.ContainsKey(eventType))
        {
            this.RegisterEvent<T>(handler);
            eventSubscriptions[eventType] = true;
        }
    }

    // ✅ 按区域的事件管理
    public class RegionalEventManager : IUtility
    {
        private readonly Dictionary<string, HashSet<IController>> regionControllers = new Dictionary<string, HashSet<IController>>();

        public void RegisterControllerToRegion(string region, IController controller)
        {
            if (!regionControllers.ContainsKey(region))
                regionControllers[region] = new HashSet<IController>();

            regionControllers[region].Add(controller);
        }

        public void SendEventToRegion<T>(string region, T eventData) where T : struct
        {
            if (regionControllers.TryGetValue(region, out var controllers))
            {
                foreach (var controller in controllers)
                {
                    // 只向特定区域的控制器发送事件
                    if (controller is MonoBehaviour mb && mb != null)
                    {
                        // 发送事件的逻辑
                    }
                }
            }
        }
    }
}

内存管理的最佳实践

// ✅ QFramework 中的内存优化技巧
public class MemoryOptimizedModel : AbstractModel, IDisposable
{
    // 使用结构体减少堆内存分配
    public struct PlayerState
    {
        public int Health;
        public int Mana;
        public Vector3 Position;
        public bool IsAlive;
    }

    private readonly BindableProperty<PlayerState> playerState = new BindableProperty<PlayerState>();

    // 缓存频繁计算的结果
    private readonly Dictionary<string, float> cachedCalculations = new Dictionary<string, float>();
    private float lastCalculationTime;

    public float GetDamageMultiplier()
    {
        const string cacheKey = "damageMultiplier";

        // 缓存 1 秒钟内的计算结果
        if (Time.time - lastCalculationTime < 1f && cachedCalculations.ContainsKey(cacheKey))
        {
            return cachedCalculations[cacheKey];
        }

        var multiplier = CalculateDamageMultiplier();
        cachedCalculations[cacheKey] = multiplier;
        lastCalculationTime = Time.time;

        return multiplier;
    }

    private float CalculateDamageMultiplier()
    {
        // 复杂的计算逻辑
        return 1.0f;
    }

    public void Dispose()
    {
        cachedCalculations.Clear();
        playerState?.Dispose();
    }
}

// ✅ 懒加载的数据管理
public class LazyLoadedDataModel : AbstractModel
{
    private readonly Dictionary<string, WeakReference> dataCache = new Dictionary<string, WeakReference>();

    public T GetData<T>(string key, System.Func<T> factory) where T : class
    {
        if (dataCache.TryGetValue(key, out var weakRef) && weakRef.IsAlive)
        {
            return weakRef.Target as T;
        }

        var data = factory();
        dataCache[key] = new WeakReference(data);
        return data;
    }

    // 定期清理已经被 GC 的弱引用
    public void CleanupWeakReferences()
    {
        var keysToRemove = new List<string>();

        foreach (var kvp in dataCache)
        {
            if (!kvp.Value.IsAlive)
            {
                keysToRemove.Add(kvp.Key);
            }
        }

        foreach (var key in keysToRemove)
        {
            dataCache.Remove(key);
        }
    }
}

QFramework 的测试和调试最佳实践

可测试性设计

QFramework 的分层架构天然支持单元测试和集成测试:

// ✅ Model 层的单元测试
[TestFixture]
public class CounterModelTests
{
    private CounterModel model;
    private TestArchitecture architecture;

    [SetUp]
    public void Setup()
    {
        architecture = new TestArchitecture();
        model = new CounterModel();
        model.SetArchitecture(architecture);
        model.Init();
    }

    [Test]
    public void IncrementCount_ShouldIncreaseByOne()
    {
        // Arrange
        var initialCount = model.Count.Value;

        // Act
        model.IncrementCount();

        // Assert
        Assert.AreEqual(initialCount + 1, model.Count.Value);
    }

    [Test]
    public void IncrementCount_ShouldSendEvent()
    {
        // Arrange
        bool eventReceived = false;
        CountChangedEvent receivedEvent = default;

        architecture.RegisterEvent<CountChangedEvent>(e => 
        {
            eventReceived = true;
            receivedEvent = e;
        });

        // Act
        model.IncrementCount();

        // Assert
        Assert.IsTrue(eventReceived);
        Assert.AreEqual(model.Count.Value, receivedEvent.NewCount);
    }

    [TearDown]
    public void TearDown()
    {
        model = null;
        architecture.Deinit();
    }
}

// ✅ 测试用的模拟架构
public class TestArchitecture : IArchitecture
{
    private readonly Dictionary<Type, object> models = new Dictionary<Type, object>();
    private readonly Dictionary<Type, object> systems = new Dictionary<Type, object>();
    private readonly Dictionary<Type, object> utilities = new Dictionary<Type, object>();

    public T GetModel<T>() where T : class, IModel
    {
        return models.TryGetValue(typeof(T), out var model) ? model as T : null;
    }

    public T GetSystem<T>() where T : class, ISystem
    {
        return systems.TryGetValue(typeof(T), out var system) ? system as T : null;
    }

    public T GetUtility<T>() where T : class, IUtility
    {
        return utilities.TryGetValue(typeof(T), out var utility) ? utility as T : null;
    }

    public void RegisterModel<T>(T model) where T : class, IModel
    {
        models[typeof(T)] = model;
    }

    public void RegisterSystem<T>(T system) where T : class, ISystem
    {
        systems[typeof(T)] = system;
    }

    public void RegisterUtility<T>(T utility) where T : class, IUtility
    {
        utilities[typeof(T)] = utility;
    }

    public void SendCommand<T>() where T : ICommand, new()
    {
        var command = new T();
        command.SetArchitecture(this);
        command.Execute();
    }

    public void SendCommand<T>(T command) where T : ICommand
    {
        command.SetArchitecture(this);
        command.Execute();
    }

    public void RegisterEvent<T>(Action<T> onEvent)
    {
        // 测试事件注册逻辑
    }

    public void UnRegisterEvent<T>(Action<T> onEvent)
    {
        // 测试事件取消注册逻辑
    }

    public void SendEvent<T>(T e)
    {
        // 测试事件发送逻辑
    }

    public void Deinit()
    {
        models.Clear();
        systems.Clear();
        utilities.Clear();
    }
}

Command 的集成测试

// ✅ Command 的集成测试
[TestFixture]
public class PurchaseItemCommandTests
{
    private TestArchitecture architecture;
    private IPlayerModel playerModel;
    private IInventoryModel inventoryModel;
    private IShopSystem shopSystem;

    [SetUp]
    public void Setup()
    {
        architecture = new TestArchitecture();

        // 模拟依赖
        playerModel = new MockPlayerModel();
        inventoryModel = new MockInventoryModel();
        shopSystem = new MockShopSystem();

        architecture.RegisterModel<IPlayerModel>(playerModel);
        architecture.RegisterModel<IInventoryModel>(inventoryModel);
        architecture.RegisterSystem<IShopSystem>(shopSystem);
    }

    [Test]
    public void PurchaseItem_WithSufficientCoins_ShouldSucceed()
    {
        // Arrange
        playerModel.Coins.Value = 100;
        var itemId = "sword";
        var price = 50;
        var command = new PurchaseItemCommand(itemId, price);

        // Act
        architecture.SendCommand(command);

        // Assert
        Assert.AreEqual(50, playerModel.Coins.Value);
        Assert.IsTrue(inventoryModel.HasItem(itemId));
    }

    [Test]
    public void PurchaseItem_WithInsufficientCoins_ShouldFail()
    {
        // Arrange
        playerModel.Coins.Value = 30;
        var itemId = "sword";
        var price = 50;
        var command = new PurchaseItemCommand(itemId, price);

        // Act & Assert
        Assert.Throws<InsufficientCoinsException>(() => 
        {
            architecture.SendCommand(command);
        });

        Assert.AreEqual(30, playerModel.Coins.Value);
        Assert.IsFalse(inventoryModel.HasItem(itemId));
    }
}

// ✅ Mock 对象的实现
public class MockPlayerModel : IPlayerModel
{
    public BindableProperty<int> Coins { get; } = new BindableProperty<int>(0);
    public BindableProperty<int> Level { get; } = new BindableProperty<int>(1);

    public void Init() { }
    public IArchitecture GetArchitecture() => null;
    public void SetArchitecture(IArchitecture architecture) { }
}

public class MockInventoryModel : IInventoryModel
{
    private readonly Dictionary<string, int> items = new Dictionary<string, int>();

    public void AddItem(string itemId, int quantity)
    {
        if (!items.ContainsKey(itemId))
            items[itemId] = 0;
        items[itemId] += quantity;
    }

    public bool HasItem(string itemId)
    {
        return items.ContainsKey(itemId) && items[itemId] > 0;
    }

    public void Init() { }
    public IArchitecture GetArchitecture() => null;
    public void SetArchitecture(IArchitecture architecture) { }
}

运行时调试工具

QFramework 可以集成强大的运行时调试工具:

// ✅ 运行时架构监控器
public class ArchitectureDebugger : MonoBehaviour
{
    [Header("架构调试信息")]
    [SerializeField] private bool showDebugInfo = true;
    [SerializeField] private KeyCode debugToggleKey = KeyCode.F1;

    private IArchitecture architecture;
    private readonly List<string> commandHistory = new List<string>();
    private readonly List<string> eventHistory = new List<string>();

    void Start()
    {
        architecture = GameApp.Interface;

        if (showDebugInfo)
        {
            // 监控所有 Command 执行
            HookCommandExecution();

            // 监控所有 Event 发送
            HookEventSending();
        }
    }

    void Update()
    {
        if (Input.GetKeyDown(debugToggleKey))
        {
            showDebugInfo = !showDebugInfo;
        }
    }

    void OnGUI()
    {
        if (!showDebugInfo) return;

        GUILayout.BeginArea(new Rect(10, 10, 400, Screen.height - 20));

        GUILayout.Label("QFramework 架构调试器", EditorStyles.boldLabel);

        // 显示最近的 Command 历史
        GUILayout.Label("Command 历史:");
        GUILayout.BeginScrollView(Vector2.zero, GUILayout.Height(150));
        foreach (var command in commandHistory.TakeLast(10))
        {
            GUILayout.Label(command);
        }
        GUILayout.EndScrollView();

        // 显示最近的 Event 历史
        GUILayout.Label("Event 历史:");
        GUILayout.BeginScrollView(Vector2.zero, GUILayout.Height(150));
        foreach (var evt in eventHistory.TakeLast(10))
        {
            GUILayout.Label(evt);
        }
        GUILayout.EndScrollView();

        // 架构状态信息
        GUILayout.Label("Model 状态:");
        DisplayModelStates();

        GUILayout.EndArea();
    }

    private void HookCommandExecution()
    {
        // 使用反射或 AOP 技术监控 Command 执行
        // 这里简化处理
    }

    private void HookEventSending()
    {
        // 使用反射或 AOP 技术监控 Event 发送
        // 这里简化处理
    }

    private void DisplayModelStates()
    {
        // 显示各个 Model 的当前状态
        if (architecture.GetModel<IPlayerModel>() is PlayerModel playerModel)
        {
            GUILayout.Label($"玩家等级: {playerModel.Level.Value}");
            GUILayout.Label($"玩家金币: {playerModel.Coins.Value}");
        }

        if (architecture.GetModel<IInventoryModel>() is InventoryModel inventoryModel)
        {
            GUILayout.Label($"背包物品数: {inventoryModel.Items.Value.Count}");
        }
    }
}

// ✅ 性能监控器
public class PerformanceMonitor : MonoBehaviour
{
    [Header("性能监控")]
    [SerializeField] private bool enableProfiling = true;

    private readonly Dictionary<string, float> commandExecutionTimes = new Dictionary<string, float>();
    private readonly Dictionary<string, int> commandExecutionCounts = new Dictionary<string, int>();

    public void LogCommandExecution(string commandName, float executionTime)
    {
        if (!enableProfiling) return;

        if (!commandExecutionTimes.ContainsKey(commandName))
        {
            commandExecutionTimes[commandName] = 0;
            commandExecutionCounts[commandName] = 0;
        }

        commandExecutionTimes[commandName] += executionTime;
        commandExecutionCounts[commandName]++;

        // 发现性能问题时警告
        if (executionTime > 0.1f) // 100ms
        {
            Debug.LogWarning($"Command {commandName} 执行耗时过长: {executionTime:F3}s");
        }
    }

    public void PrintPerformanceReport()
    {
        Debug.Log("=== QFramework 性能报告 ===");

        foreach (var kvp in commandExecutionTimes)
        {
            var commandName = kvp.Key;
            var totalTime = kvp.Value;
            var count = commandExecutionCounts[commandName];
            var averageTime = totalTime / count;

            Debug.Log($"{commandName}: 总耗时 {totalTime:F3}s, 执行次数 {count}, 平均耗时 {averageTime:F3}s");
        }
    }
}

QFramework 的渐进式架构演进策略

架构成熟度模型

成熟度级别 特征描述 适用项目规模 演进重点
初始级 功能优先、快速实现 小型项目、原型验证 建立基本结构
管理级 规范流程、模块划分 中型项目、团队协作 制定开发规范
定义级 标准化开发、质量保证 大型项目、长期维护 建立质量体系
量化级 数据驱动、性能监控 商业产品、高要求 优化关键指标
优化级 持续改进、自动化 企业级、多项目 平台化建设
}

private void OnItemsChanged(List<ItemData> items)
{
    // 清理旧的 UI
    foreach (var view in itemViews)
    {
        if (view != null)
            Destroy(view.gameObject);
    }
    itemViews.Clear();

    // 创建新的 UI
    foreach (var item in items)
    {
        var itemView = Instantiate(itemPrefab, itemContainer);
        itemView.SetData(item);
        itemView.OnItemClicked += (clickedItem) => 
        {
            this.SendCommand<UseItemCommand>(new UseItemCommand(clickedItem.Id));
        };
        itemViews.Add(itemView);
    }
}

private void OnCapacityChanged(int capacity)
{
    var currentCount = inventoryModel.Items.Value.Count;
    capacityText.text = $"{currentCount}/{capacity}";

    // 容量警告
    if (currentCount >= capacity * 0.9f)
    {
        capacityText.color = Color.red;
    }
    else if (currentCount >= capacity * 0.7f)
    {
        capacityText.color = Color.yellow;
    }
    else
    {
        capacityText.color = Color.white;
    }
}

private void OnItemUsed(ItemUsedEvent e)
{
    // 播放使用物品的特效
    PlayItemUseEffect(e.ItemId);
}

public IArchitecture GetArchitecture() => RPGGameApp.Interface;

}

// ✅ 可复用的物品视图组件 public class InventoryItemView : MonoBehaviour { [SerializeField] private Image iconImage; [SerializeField] private Text nameText; [SerializeField] private Text quantityText; [SerializeField] private Button useButton;

public event System.Action<ItemData> OnItemClicked;

private ItemData itemData;

void Start()
{
    useButton.onClick.AddListener(() => 
    {
        OnItemClicked?.Invoke(itemData);
    });
}

public void SetData(ItemData data)
{
    itemData = data;
    iconImage.sprite = data.Icon;
    nameText.text = data.Name;
    quantityText.text = data.Quantity > 1 ? data.Quantity.ToString() : "";

    // 根据物品类型设置不同的显示状态
    useButton.interactable = data.IsUsable;
}

}

### QFramework 的性能优化最佳实践

#### 事件系统的性能优化

QFramework 的事件系统在大量事件监听和发送时的性能优化:

```csharp
// ✅ 优化的事件处理
public class OptimizedEventSystem : MonoBehaviour
{
    // 使用对象池减少 GC
    private static readonly ObjectPool<List<System.Action>> ActionListPool = 
        new ObjectPool<List<System.Action>>(() => new List<System.Action>(), null, l => l.Clear());

    void Start()
    {
        // 批量事件处理
        var actions = ActionListPool.Get();

        // 收集所有需要执行的事件
        CollectPendingEvents(actions);

        // 批量执行
        foreach (var action in actions)
        {
            action?.Invoke();
        }

        // 回收对象
        ActionListPool.Release(actions);
    }

    // ✅ 按需加载的事件监听
    private readonly Dictionary<System.Type, bool> eventSubscriptions = new Dictionary<System.Type, bool>();

    private void RegisterEventOnDemand<T>(System.Action<T> handler) where T : struct
    {
        var eventType = typeof(T);

        if (!eventSubscriptions.ContainsKey(eventType))
        {
            this.RegisterEvent<T>(handler);
            eventSubscriptions[eventType] = true;
        }
    }

    // ✅ 按区域的事件管理
    public class RegionalEventManager : IUtility
    {
        private readonly Dictionary<string, HashSet<IController>> regionControllers = new Dictionary<string, HashSet<IController>>();

        public void RegisterControllerToRegion(string region, IController controller)
        {
            if (!regionControllers.ContainsKey(region))
                regionControllers[region] = new HashSet<IController>();

            regionControllers[region].Add(controller);
        }

        public void SendEventToRegion<T>(string region, T eventData) where T : struct
        {
            if (regionControllers.TryGetValue(region, out var controllers))
            {
                foreach (var controller in controllers)
                {
                    // 只向特定区域的控制器发送事件
                    if (controller is MonoBehaviour mb && mb != null)
                    {
                        // 发送事件的逻辑
                    }
                }
            }
        }
    }
}

内存管理的最佳实践

// ✅ QFramework 中的内存优化技巧
public class MemoryOptimizedModel : AbstractModel, IDisposable
{
    // 使用结构体减少堆内存分配
    public struct PlayerState
    {
        public int Health;
        public int Mana;
        public Vector3 Position;
        public bool IsAlive;
    }

    private readonly BindableProperty<PlayerState> playerState = new BindableProperty<PlayerState>();

    // 缓存频繁计算的结果
    private readonly Dictionary<string, float> cachedCalculations = new Dictionary<string, float>();
    private float lastCalculationTime;

    public float GetDamageMultiplier()
    {
        const string cacheKey = "damageMultiplier";

        // 缓存 1 秒钟内的计算结果
        if (Time.time - lastCalculationTime < 1f && cachedCalculations.ContainsKey(cacheKey))
        {
            return cachedCalculations[cacheKey];
        }

        var multiplier = CalculateDamageMultiplier();
        cachedCalculations[cacheKey] = multiplier;
        lastCalculationTime = Time.time;

        return multiplier;
    }

    private float CalculateDamageMultiplier()
    {
        // 复杂的计算逻辑
        return 1.0f;
    }

    public void Dispose()
    {
        cachedCalculations.Clear();
        playerState?.Dispose();
    }
}

// ✅ 懒加载的数据管理
public class LazyLoadedDataModel : AbstractModel
{
    private readonly Dictionary<string, WeakReference> dataCache = new Dictionary<string, WeakReference>();

    public T GetData<T>(string key, System.Func<T> factory) where T : class
    {
        if (dataCache.TryGetValue(key, out var weakRef) && weakRef.IsAlive)
        {
            return weakRef.Target as T;
        }

        var data = factory();
        dataCache[key] = new WeakReference(data);
        return data;
    }

    // 定期清理已经被 GC 的弱引用
    public void CleanupWeakReferences()
    {
        var keysToRemove = new List<string>();

        foreach (var kvp in dataCache)
        {
            if (!kvp.Value.IsAlive)
            {
                keysToRemove.Add(kvp.Key);
            }
        }

        foreach (var key in keysToRemove)
        {
            dataCache.Remove(key);
        }
    }
}
成熟度级别 特征描述 适用项目规模 演进重点
初始级 功能优先、快速实现 小型项目、原型验证 建立基本结构
管理级 规范流程、模块划分 中型项目、团队协作 制定开发规范
定义级 标准化开发、质量保证 大型项目、长期维护 建立质量体系
量化级 数据驱动、性能监控 商业产品、高要求 优化关键指标
优化级 持续改进、自动化 企业级、多项目 平台化建设

团队协作和知识传承

知识管理策略

graph LR
    A[知识获取] --> B[知识整理]
    B --> C[知识分享]
    C --> D[知识应用]
    D --> E[知识创新]
    E --> A

    F[代码评审] --> B
    G[技术文档] --> C
    H[培训分享] --> C
    I[最佳实践] --> D
    J[工具平台] --> E

常见陷阱和解决方案

架构反模式识别

反模式名称 症状描述 危害分析 解决方案
神类模式 单个类承担过多职责 难以维护、测试困难 应用单一职责原则拆分
复制粘贴编程 大量重复代码 维护成本高、错误传播 提取公共抽象和工具类
硬编码配置 配置值写死在代码中 灵活性差、难以调优 使用配置文件和数据驱动
循环依赖 模块间相互依赖 耦合度高、难以解耦 引入中介者或事件机制
过度设计 提前优化、过度抽象 复杂度高、开发效率低 按需设计、渐进式重构

结论

Unity 中的 C# 代码设计是一个系统性工程,需要在数据容器设计、接口驱动开发、组件化架构等多个维度上建立正确的设计理念。通过遵循 SOLID 原则,采用事件驱动和数据驱动的设计模式,结合 Unity 特性进行架构优化,可以构建出高质量、易维护、可扩展的游戏项目。

成功的架构设计不是一蹴而就的,而是需要在项目实践中不断演进和完善。关键在于建立正确的设计思维,掌握核心的设计原则,并在团队中形成良好的开发规范和知识传承机制。