--- title: "Unity Architect Agent Personality" type: source tags: [unity, game-engineering, architecture, scriptableobjects, design-patterns] date: 2026-05-02 --- ## Source File - [[Agent/agency-agents/game-development/unity/unity-architect.md]] ## Summary(用中文描述) - 核心主题:Unity 游戏架构中的数据驱动、模块化设计方法论,基于 ScriptableObject 构建可扩展系统 - 问题域:Unity 项目中常见的代码耦合、单体类蔓延、硬编码引用等架构腐败问题 - 方法/机制:ScriptableObject First Design + 单职责组件模式 + SO 事件通道 + RuntimeSet 追踪 - 结论/价值:消除 GameObject 中心主义,通过 SO 资产实现设计师友好、可测试、易扩展的架构 ## Key Claims(用中文描述) - 所有共享游戏数据必须存于 ScriptableObject,不得通过 MonoBehaviour 字段跨场景传递 - 每个 MonoBehaviour 只解决一个问题,超过 150 行几乎必然违反 SRP - 跨系统通信必须通过 SO 事件通道,禁止 `GameObject.Find()`、`FindObjectOfType()`、静态单例 - Prefab 必须完全自包含,放入空场景无错误;序列化脚本修改必须调用 `EditorUtility.SetDirty()` ## Key Quotes > "Eliminate hard references between systems using ScriptableObject event channels" — SO 事件通道替代硬引用 > "Every prefab dragged into a scene must be fully self-contained — no assumptions about scene hierarchy" — Prefab 自包含原则 > "If a class exceeds ~150 lines, it is almost certainly violating SRP" — 代码行数红线 ## Key Concepts - [[ScriptableObject]]:Unity 资产,可存储数据无需挂载到 GameObject,用于变量、事件、运行时集合 - [[Single Responsibility Principle]]:每个 MonoBehaviour 仅负责一个职责,超长组件必须拆分 - [[Event Channel Pattern]]:SO 事件通道(GameEvent)实现跨系统解耦通信 - [[RuntimeSet]]:ScriptableObject 管理的实体运行时集合,无单例开销 - [[Addressables]]:Unity 资源管理系统,替代 Resources.Load,支持细粒度内存控制和 DLC - [[DOTS (Data-Oriented Tech Stack)]]:Unity ECS,Job System + Burst Compiler 优化性能关键路径 - [[Burst Compiler]]:将 C# Job 代码编译为近乎原生性能的机器码 - [[Data-Oriented Design]]:面向数据的设计,与面向对象互补,提升 CPU 缓存命中率 ## Key Entities - **UnityArchitect**:角色名,资深 Unity 工程师,数据驱动模块化设计专家,拒绝 GameObject 中心主义 - **FloatVariable**:SO 变量资产示例,支持运行时值变更事件 - **GameEvent**:SO 事件通道资产,用于跨 MonoBehaviour 解耦通信 - **RuntimeSetRegistrar**:MonoBehaviour,在 OnEnable/OnDisable 时向 RuntimeSet 注册/注销 ## Connections - [[Unity Multiplayer Engineer]] ← extends ← [[Unity Architect]](多人网络扩展基础架构) - [[Unity Shader Graph Artist]] ← extends ← [[Unity Architect]](渲染管线基础架构) - [[Unity Editor Tool Developer]] ← extends ← [[Unity Architect]](Editor 工具基础架构) - [[Godot Gameplay Scripter]] ← parallels ← [[Unity Architect]](跨引擎设计模式对应) - [[Roblox Systems Scripter]] ← parallels ← [[Unity Architect]](跨平台代码架构模式) ## Contradictions - 与传统 Unity "Manager Singleton" 惯用法冲突: - 冲突点:是否允许静态单例管理跨系统状态 - 当前观点:所有共享状态置于 SO 资产,通过 Inspector 引用,消除全局可变状态 - 对方观点:单例简单直接,访问全局状态无需显式依赖注入 ## Technical Deliverables(关键代码模式) ### FloatVariable SO ```csharp [CreateAssetMenu(menuName = "Variables/Float")] public class FloatVariable : ScriptableObject { [SerializeField] private float _value; public float Value { get => _value; set { _value = value; OnValueChanged?.Invoke(value); } } public event Action OnValueChanged; public void SetValue(float value) => Value = value; public void ApplyChange(float amount) => Value += amount; } ``` ### GameEvent Channel(解耦消息) ```csharp [CreateAssetMenu(menuName = "Events/Game Event")] public class GameEvent : ScriptableObject { private readonly List _listeners = new(); public void Raise() { for (int i = _listeners.Count - 1; i >= 0; i--) _listeners[i].OnEventRaised(); } public void RegisterListener(GameEventListener listener) => _listeners.Add(listener); public void UnregisterListener(GameEventListener listener) => _listeners.Remove(listener); } ``` ### RuntimeSet(无单例实体追踪) ```csharp public abstract class RuntimeSet : ScriptableObject { public List Items = new List(); public void Add(T item) { if (!Items.Contains(item)) Items.Add(item); } public void Remove(T item) { if (Items.Contains(item)) Items.Remove(item); } } ``` ## Workflow Process 1. **Architecture Audit**:识别硬引用、单例、God Class,映射数据流 2. **SO Asset Design**:创建 Variable SO、Event Channel SO、RuntimeSet SO,按领域组织 3. **Component Decomposition**:拆分 God MonoBehaviour 为单职责组件,通过 SO 引用连接 4. **Editor Tooling**:添加 CustomEditor/PropertyDrawer,[CreateAssetMenu],构建时架构验证 5. **Scene Architecture**:场景无持久数据,使用 Addressables + SO 配置驱动场景加载 ## Success Metrics - 生产代码中零 `GameObject.Find()` 或 `FindObjectOfType()` 调用 - 每个 MonoBehaviour < 150 行,仅处理一个关注点 - 每个 Prefab 可在空场景中独立运行无错误 - GC 分配在事件驱动路径上为零帧 - 设计师无需修改代码即可通过 Inspector 创建新游戏变量和事件