关于 unity-architecture
unity-architecture 是面向 Unity 开发者的架构建议技能,用于规划代码结构或重构。它按项目规模建议模块划分,并强调明确初始化顺序、更新前置条件和避免过度抽象。
主要功能
- 01按项目规模推荐架构
- 02划分模块与层级职责
- 03明确启动顺序
- 04为更新添加就绪检查
- 05避免过度设计
适用场景
- 01规划新游戏的代码结构
- 02重构时降低耦合
- 03检查初始化与更新假设
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ besty0728/ unity-skills --skill unity-architecture安装后在 Claude Code 中输入/unity-architecture确认已加载。
详细介绍
**调用此模块中的任何技能之前:**如果你打算根据技能名称或描述猜测参数后调用技能,请停止——先阅读此文件(或通过
GET /skills/recommend?includeSchema=true获取其架构)。如果你已经通过 recommend/schema 获得参数定义,则可以直接进行 dryRun。
触发条件
- 规划代码组织
- 划分职责
- 降低耦合
- 选择重构方向
- 规划代码结构、划分职责、降低耦合、确定重构方向
Unity 架构顾问
在生成大量游戏玩法脚本之前,或用户要求采用更清晰的架构时使用。
工作流
- 确定范围:原型、小型游戏或长期项目。
- 定义核心循环和所需的最少运行时系统。
- 推荐与范围相符的最精简架构。
- 分离以下部分:
- 场景/引导层
- 游戏玩法/领域逻辑
- 数据/配置资源
- 视图/表现层
- 指出哪些部分现在应保持简单,哪些部分值得抽象。
输出格式
使用此技能时,请按以下结构提供建议:
- 项目层级:原型/小型游戏/长期项目
- 推荐模块:3–7 个模块,每个模块用一行说明职责
- 场景/引导方案:组合与初始化发生的位置
- 数据归属:哪些内容属于场景对象、ScriptableObjects 或纯 C# 类
- 通信规则:直接引用、接口、事件或命令
- 性能风险:仅指出重要的热点路径
- 现在该做/暂不处理:避免过度设计
默认指导原则
- 优先使用精简的
MonoBehaviour脚本作为组合桥接层。 - 尽可能将可复用的游戏玩法规则放入纯 C# 类。
- 使用
ScriptableObject存储创作配置和共享静态数据,不要默认将其用作运行时状态的存放处。 - 明确依赖关系。除非项目规模足以证明引入小型服务层是合理的,否则应避免隐藏的全局状态。
- 优先采用简单的模块边界,而不是依赖繁重框架的架构。
明确执行顺序与入口保护
大多数看似“随机”的游戏玩法错误,都源于两个未明说的假设:脚本会按可预测的顺序运行,以及只有在数据就绪时才会运行 Update。除非你明确保证,否则这两点都不成立。
明确启动顺序
不要依赖 Script Execution Order 面板或偶然的 Awake 顺序。按以下优先顺序采用这些模式:
- 使用一个 Bootstrap 脚本作为唯一入口。它负责初始化顺序,并对其创建的管理器调用
sub.Init()。只有这一个脚本带有[DefaultExecutionOrder(-10000)]。 - 主动拉取,而非推送:需要数据的订阅者按需调用
source.GetValue(),或订阅事件。发布者在自身的Awake中向其他对象推送数据,会造成隐藏的顺序依赖。 - 仅对承载关键职责的单例保留
[DefaultExecutionOrder(n)](Bootstrap、InputRouter、SceneController)。如果需要它的脚本超过 3–4 个,说明架构有问题,而不是排序有问题。
类似的 ECS 模式——[UpdateBefore(typeof(BarSystem))] / [UpdateAfter]——之所以有效,是因为框架会在排序时验证矛盾。在 MonoBehaviour 代码中,编译器不会捕获这些问题;请谨慎使用。来源:EntitiesSamples/Docs/systems.md:32——“如果某个组的子项排序属性彼此矛盾,就会抛出异常”。
明确更新前置条件
每个 Update / LateUpdate / FixedUpdate 都应以保护子句开头,在系统尚未就绪时提前返回。优先执行开销最低的检查:
void Update() {
if (!_isInitialized) return; // construction-time
if (_dataSource == null) return; // dependency-level
if (_paused) return; // gameplay-state
// real work here
}
缺少保护条件,区别就在于“尚未运行”(安全)和“使用过时/空数据运行,并悄无声息地破坏状态”(调试噩梦)。ECS 中对应的做法是在 OnCreate 中使用 state.RequireForUpdate<Config>(),将前置条件转化为系统级不变量。来源:Dots101/Entities101/Assets/HelloCube/3. Prefabs/SpawnSystem.cs:17-19——只有存在 Spawner 实体时,系统才会更新。
守则
模式:仅限文档——没有需要管控的 REST 技能;在任何运行模式(Approval / Auto / Bypass)下均可自由加载。
- 除非项目确实需要,否则不要一开始就搭建庞大的可复用框架。
- 不要只为符合教科书式的 SOLID 表述而增加层级。
- 优先采用能够逐步扩展的小型架构,而不是会拖慢迭代速度、看起来很厉害的架构。
按需加载相关建议模块
- 模式选择:参见
../patterns/SKILL.md - Async / Update / UniTask 决策:参见
../async/SKILL.md - 面向 Inspector 的字段设计:参见
../inspector/SKILL.md - 脚本质量审查:参见
../scriptdesign/SKILL.md