关于 Unity Refactor
用于分析 Unity C# 代码库、按风险排列代码异味,并逐项执行重构的技能。它会在每次修改后检查引用和编译,目标是在保持现有行为的前提下改善代码。
主要功能
- 01扫描 Unity 代码异味
- 02按风险排列重构优先级
- 03修改前展示计划
- 04每次只执行一项重构
- 05检查引用和编译
适用场景
- 01审查 Unity 脚本中的技术债
- 02拆分过长的方法或管理器类
- 03将魔法字符串替换为常量
- 04减少系统间的直接依赖
MCP 相关
此技能不依赖 Unity MCP 服务;它使用 Read、Write、Edit、Grep、Glob 和 Bash 工具。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ juliankerignard/ unity-skills --skill unity-refactor安装后在 Claude Code 中输入/unity-refactor确认已加载。
附带文件references/refactor-recipes.md
详细介绍
Unity 重构
此技能的作用
此技能会分析 Unity C# 代码库以检测代码异味,按风险级别提出优先级排序的重构计划,然后逐项执行更改,并在每次修改后进行验证。目标是在不改变现有行为的前提下提升代码质量。
前提条件
- Unity 项目中已有
Assets/Scripts/下的 C# 代码 - 不依赖 Unity MCP:仅使用 Read、Write、Edit、Grep、Glob、Bash
决策树
Quel type de dette technique ?
|
+-- Code trop long / illisible ?
| +-- Fichier > 500 lignes --> God class split (risque eleve)
| +-- Methode > 50 lignes --> Extraction de methodes (risque faible)
|
+-- Couplage fort entre classes ?
| +-- References directes cross-systeme --> Event Channel SO (risque moyen)
| +-- Singleton partout --> SO / Service Locator (risque eleve)
|
+-- API obsolete ?
| +-- Old Input --> New Input System (risque moyen, recette 6)
| +-- Coroutines --> async Awaitable (risque moyen, recette 4)
|
+-- Code smells generaux ?
+-- Magic strings --> Constantes / enum (risque faible)
+-- Champs publics --> [SerializeField] private (risque faible)
详细方案请参见下方的重构目录。
快速开始
- 扫描代码库以检测代码异味
- 按风险对重构进行分类和排序
- 向用户展示计划
- 一次执行一项重构
- 每次更改后验证编译和引用
- 重复以上步骤,直到完成计划
分步指南
步骤 1:扫描代码库以检测代码异味
使用 Grep、Glob 和 Bash 并行运行所有检测:
Glob : Assets/Scripts/**/*.cs # Tous les fichiers C#
Bash : find Assets/Scripts -name "*.cs" -exec wc -l {} + | sort -rn | head -20 # Fichiers volumineux
Grep : "static\s+\w+\s+Instance" dans Assets/Scripts/**/*.cs # Singletons
Grep : "void\s+Update\s*\(\)" dans Assets/Scripts/**/*.cs # Update polling
Grep : "Find\(\"" dans Assets/Scripts/**/*.cs # Magic strings (Find)
Grep : "CompareTag\(\"" dans Assets/Scripts/**/*.cs # Magic strings (Tags)
Grep : "StartCoroutine" dans Assets/Scripts/**/*.cs # Coroutine spaghetti
Grep : "public\s+(?!void|static|override|class)" dans *.cs # Champs publics exposes
Grep : "class\s+\w+\s*:\s*\w+" dans Assets/Scripts/**/*.cs # Heritage (tracer les chaines)
步骤 2:分类和排序
使用下方的重构目录对检测到的每项代码异味进行分类。
Unity 重构目录
| 代码异味 | 检测模式(Grep) | 重构 | 风险 |
|---|---|---|---|
| 上帝管理器(>500 行) | 包含 “Manager” 且超过 500 行的 .cs 文件 | 拆分为职责明确的服务 | 高 |
| Singleton MonoBehaviour | MonoBehaviour 中的 static.*Instance.*get | 替换为 SO + Service Locator | 高 |
| 深层继承(>3 层) | 超过 3 层的 class X : Y 链 | 使用组合 + 接口扁平化 | 高 |
| Update 轮询 | 带有布尔检查的 Update() | 替换为事件/回调 | 中 |
| 上帝式 Update | 包含 >5 项职责的 Update() | 拆分为独立组件 | 中 |
| 特性嫉妒 | 大量访问其他类数据的方法 | 将方法移至数据所属类 | 中 |
| 原始类型沉迷 | 重复出现的 int/float/string 组 | 提取为值类型/struct | 中 |
| 魔法字符串 | Find/CompareTag/Animator 中的 "string" | 替换为 const/enum/SO | 低 |
| Inspector 公共字段 | 大量 public 字段 | 使用 [SerializeField] private + SO 配置 | 低 |
| 巨型方法(>50 行) | 过长的方法 | 提取子方法 | 低 |
检测阈值
| 指标 | 阈值 | 判定 |
|---|---|---|
| 每个类的行数 | > 500 | 上帝类 |
| 每个方法的行数 | > 50 | 方法过长 |
| 每个类的方法数 | > 15 | 职责过多 |
| 每个方法的参数数 | > 5 | 需要参数对象 |
| 继承层级 | > 3 | 扁平化继承层次 |
优先级顺序:低(魔法字符串、公共字段、长方法),然后是 中(Update 轮询、特性嫉妒、上帝式 Update),最后是 高(单例、上帝类、继承)。
步骤 3:向用户展示计划
进行任何修改前,先展示一个表格:# | 文件 | 代码异味 | 重构 | 风险 | 受影响文件。提供 全部 / 选择 / 取消 选项。开始前等待确认。
步骤 4:一次执行一项重构
针对已批准计划中的每项重构:
1. Read : Lire le fichier cible completement
2. Grep : Identifier TOUTES les references au code qui va changer
Grep : "NomClasse" dans Assets/Scripts/**/*.cs
Grep : "NomMethode" dans Assets/Scripts/**/*.cs
3. Edit : Effectuer le changement (une seule modification atomique)
4. Edit : Mettre a jour toutes les references trouvees
5. Grep : Verifier qu'aucune reference orpheline ne subsiste
6. Passer au refactoring suivant
步骤 5:每次更改后验证
每项重构完成后:
1. Grep pour les anciens noms de classes/methodes : doit retourner 0 resultats
2. Grep pour les references cassees : "using.*OldNamespace" absent
3. Verifier coherence : les nouveaux fichiers sont dans le bon dossier
4. Verifier que les [SerializeField] et references Inspector ne sont pas casses
如果检测到问题,撤销更改,并在继续前通知用户。
步骤 6:重复以上步骤,直到完成
按优先级顺序遍历计划(先处理低风险项)。每项重构完成后,报告进度:
[2/8] Termine : EnemyController.cs - Extraction de methodes
Fichiers modifies : 1
References mises a jour : 0
Status : OK
重构配方
references/refactor-recipes.md 中包含 6 个详细配方,附有重构前后的代码:
| 配方 | 风险 | 描述 |
|---|---|---|
| Singleton 转为 SO Service | 高 | 将 MonoBehaviour 单例替换为注入的 ScriptableObject |
| God Manager 转为服务 | 高 | 将单体管理器拆分为职责明确的服务 |
| 魔法字符串转为常量 | 低 | 将字符串提取为常量,并使用 Animator.StringToHash |
| 协程转为 async Awaitable | 中 | 将 IEnumerator 迁移为 async Awaitable(Unity 6+) |
| 直接引用转为 Event Channel | 中 | 使用 ScriptableObject events 解耦发布者与订阅者 |
| Old Input 转为 New Input System | 中 | 从 UnityEngine.Input 迁移到 InputSystem |
严格规则
- 绝不在同一个文件上同时进行 2 项重构
- 绝不改变可观察到的行为(重构 ≠ 新功能)
- 绝不在未提醒 Inspector 引用会丢失的情况下重命名
[SerializeField]字段 - 绝不在未通过 Grep 检查所有引用(搜索整个项目)的情况下删除代码
- 绝不在未先完整阅读文件的情况下重构文件
- 始终在每次单独修改后检查是否能编译
- 始终在重命名后通过 Grep 检查是否有引用失效
- 始终在首次修改前展示完整计划
- 始终从低风险重构开始
- 始终优先选择最小幅度的改动
- 始终使用 Edit(而非 Write)修改现有文件
- 始终保留 Unity 属性(
[SerializeField]、[Header]、[Tooltip]等)
相关技能
- 生成新的整洁代码?使用
/unity-code-gen(Unity Code Gen) - 性能审计(仅检测,不重构)?使用
/perf-audit(Unity Perf Audit) - 重构后测试代码?使用
/unity-test(Unity Test) - 诊断重构期间发现的 bug?使用
/unity-debug(Unity Debug)
故障排除
| 问题 | 解决方案 |
|---|---|
| 字段重命名后 Inspector 引用失效 | [SerializeField] 字段已重命名。使用 [FormerlySerializedAs("oldName")] 迁移序列化数据 |
| 拆分类后出现编译错误 | 检查新文件中是否缺少 using,以及程序集定义引用是否正确 |
| 重构后行为发生变化 | 撤销更改(使用 Edit 还原),分析差异,然后采用更保守的方案重新修改 |
| Prefab override 丢失 | 字段名称或类型已更改。添加 [FormerlySerializedAs],并重新检查相关 Prefab |
| 拆分后出现循环依赖 | 在共享程序集中提取接口,或通过 SO event channel 反转依赖关系 |
| 重构后测试失败 | 测试针对的是实现(方法名称),而非行为。更新测试以使用新的名称 |
| AnimatorController 引用失效 | 字符串参数已替换为哈希值。检查 Animator.StringToHash 使用的字符串是否与 controller 中的字符串相同 |
| ScriptableObject 引用为空 | 项目中尚未创建 SO 资源。通过 Create 菜单创建资源,并在 Inspector 中分配 |
评论
支持 Markdown