Update nexus wiki content
This commit is contained in:
@@ -1,58 +1,114 @@
|
||||
---
|
||||
title: "Unity Architect"
|
||||
title: "Unity Architect Agent Personality"
|
||||
type: source
|
||||
tags: []
|
||||
date: 2026-04-26
|
||||
tags: [unity, game-engineering, architecture, scriptableobjects, design-patterns]
|
||||
date: 2026-05-02
|
||||
---
|
||||
|
||||
## Source File
|
||||
- [[raw/Agent/agency-agents/game-development/unity/unity-architect.md]]
|
||||
- [[Agent/agency-agents/game-development/unity/unity-architect.md]]
|
||||
|
||||
## Summary(用中文描述)
|
||||
- 核心主题:Unity 游戏架构师 AI Agent 人格规范,专注于数据驱动、ScriptableObject(SO)优先的模块化可扩展架构
|
||||
- 问题域:如何构建避免"意大利面条式代码"的 Unity 项目,消除硬引用、单例滥用、God MonoBehaviour 等反模式
|
||||
- 方法/机制:ScriptableObject 事件通道(GameEvent)、RuntimeSet 无单例实体追踪、单一职责组件拆分、Inspector SO 引用连线、Custom PropertyDrawer 设计师赋能、Addressables 资源管理、Unity DOTS/ECS 混合架构
|
||||
- 结论/价值:通过 SO-first 设计,Unity 项目实现零 GameObject.Find()、每个 MonoBehaviour < 150 行、Prefab 场景无关自包含、设计师无需代码即可创建游戏变量/事件/运行时集合
|
||||
- 核心主题:Unity 游戏架构中的数据驱动、模块化设计方法论,基于 ScriptableObject 构建可扩展系统
|
||||
- 问题域:Unity 项目中常见的代码耦合、单体类蔓延、硬编码引用等架构腐败问题
|
||||
- 方法/机制:ScriptableObject First Design + 单职责组件模式 + SO 事件通道 + RuntimeSet 追踪
|
||||
- 结论/价值:消除 GameObject 中心主义,通过 SO 资产实现设计师友好、可测试、易扩展的架构
|
||||
|
||||
## Key Claims(用中文描述)
|
||||
- ScriptableObject-First 设计:所有共享游戏数据必须存于 ScriptableObject,绝不通过 MonoBehaviour 字段跨场景传递
|
||||
- GameEvent 事件通道:跨系统通信禁止使用 GetComponent<> 或单例,必须通过 SO 事件通道连线
|
||||
- RuntimeSet 无单例追踪:全局实体追踪使用 RuntimeSet : ScriptableObject 而非静态单例
|
||||
- 单一职责强制:每个 MonoBehaviour 只解决一个问题,若能用"and"描述则必须拆分
|
||||
- 反模式零容忍:God MonoBehaviour(500+ 行)、DontDestroyOnLoad 单例滥用、Update 内轮询逻辑均为禁止项
|
||||
- Unity DOTS 混合架构:性能关键系统迁移至 Entities(ECS),编辑器友好型游戏逻辑保留 MonoBehaviour
|
||||
- 所有共享游戏数据必须存于 ScriptableObject,不得通过 MonoBehaviour 字段跨场景传递
|
||||
- 每个 MonoBehaviour 只解决一个问题,超过 150 行几乎必然违反 SRP
|
||||
- 跨系统通信必须通过 SO 事件通道,禁止 `GameObject.Find()`、`FindObjectOfType()`、静态单例
|
||||
- Prefab 必须完全自包含,放入空场景无错误;序列化脚本修改必须调用 `EditorUtility.SetDirty()`
|
||||
|
||||
## Key Quotes
|
||||
> "Every MonoBehaviour solves one problem only — if you can describe a component with 'and,' split it." — 单一职责原则核心表述
|
||||
> "Treat every scene load as a clean slate — no transient data should survive scene transitions unless explicitly persisted via SO assets." — 场景卫生核心原则
|
||||
> "Designer-accessible: Non-technical team members can create new game variables, events, and runtime sets without touching code." — 设计师赋能核心价值
|
||||
> "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 资产形式的可序列化对象,用于存储共享数据、事件通道、运行时集合
|
||||
- [[RuntimeSet]]:继承 ScriptableObject 的泛型集合类型,用于全局追踪活跃实体而不依赖单例
|
||||
- [[GameEvent]]:SO 形式的事件通道(GameEvent : ScriptableObject),用于跨系统解耦通信
|
||||
- [[SingleResponsibilityPrinciple]]:每个 MonoBehaviour 只负责单一职责,超过 150 行即违反
|
||||
- [[EventDrivenArchitecture]]:事件驱动替代 Update() 内轮询,消除 GC 分配
|
||||
- [[DataDrivenDesign]]:数据驱动的模块化 Unity 架构设计理念
|
||||
- [[ScriptableObjectEventChannel]]:ScriptableObject 形式的 GameEvent 系统,通过 Raise/Register 模式实现松耦合
|
||||
- [[Addressables]]:Unity 资源管理系统,替代 Resources.Load(),支持细粒度内存控制和 DLC
|
||||
- [[UnityDOTS]]:Data-Oriented Tech Stack,ECS + Job System + Burst Compiler,用于性能关键路径
|
||||
- [[EditorUtilitySetDirty]]:编辑器脚本修改 SO 数据后必须调用以确保序列化持久化
|
||||
- [[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]]:本文档定义的 AI Agent 人格,数据驱动模块化架构专家,精通 ScriptableObject、职责拆分、单例消除
|
||||
- [[UnityEditor]]:Unity 编辑器环境,ScriptableObject 通过 [CreateAssetMenu] 对设计师可见
|
||||
- [[UnityDOTS]]:Unity Data-Oriented Tech Stack(Entities、Jobs、Burst),用于 CPU 密集型批量操作
|
||||
- **UnityArchitect**:角色名,资深 Unity 工程师,数据驱动模块化设计专家,拒绝 GameObject 中心主义
|
||||
- **FloatVariable**:SO 变量资产示例,支持运行时值变更事件
|
||||
- **GameEvent**:SO 事件通道资产,用于跨 MonoBehaviour 解耦通信
|
||||
- **RuntimeSetRegistrar**:MonoBehaviour,在 OnEnable/OnDisable 时向 RuntimeSet 注册/注销
|
||||
|
||||
## Connections
|
||||
- [[UnityArchitect]] ← builds_with ← [[ScriptableObject]]
|
||||
- [[UnityArchitect]] ← extends ← [[UnityMultiplayerEngineer]](网络层叠加 SO 架构)
|
||||
- [[UnityArchitect]] ← complements ← [[UnityShaderGraphArtist]](SO 数据驱动视觉资产)
|
||||
- [[UnityArchitect]] ← complements ← [[UnityEditorToolDeveloper]](Custom PropertyDrawer 赋能 SO 设计师体验)
|
||||
- [[UnityArchitect]] ← builds_with ← [[UnityDOTS]](性能关键路径使用 ECS 混合架构)
|
||||
- [[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
|
||||
- 与 [[UnityMultiplayerEngineer]] 在客户端预测实现上存在框架差异:
|
||||
- UnityArchitect 侧:NetworkVariable 通过 SO 引用在 MonoBehaviour 间传递状态
|
||||
- UnityMultiplayerEngineer 侧:NetworkVariable 直接挂载在 NetworkBehaviour 上
|
||||
- 两者均遵循服务器权威原则,差异在于 SO 层抽象程度,属架构风格差异而非绝对冲突
|
||||
- 与传统 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<float> 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<GameEventListener> _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<T> : ScriptableObject
|
||||
{
|
||||
public List<T> Items = new List<T>();
|
||||
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 创建新游戏变量和事件
|
||||
|
||||
Reference in New Issue
Block a user