Unity Perf Audit by juliankerignard/unity-skills
npx skills add https://github.com/juliankerignard/unity-skills --skill 'Unity Perf Audit'对 Unity 项目的 C# 代码进行静态分析,以检测性能反模式。无需运行游戏或进行性能分析——我们使用 Grep 和 Glob 扫描源代码。
产出:
Assets/ 目录下包含 C# 脚本的 Unity 项目Symptome rapporte ?
|
+-- FPS bas en general --> Lancer le scan complet (etapes 1-5)
+-- Spikes ponctuels / stuttering --> Focus CPU (anti-patterns C1-C12)
+-- Memoire qui grimpe / crashs OOM --> Focus Memory (anti-patterns M1-M7)
+-- Rendu lent, draw calls hauts --> Focus GPU (anti-patterns G1-G5)
+-- Pas de symptome precis (audit preventif) --> Scan complet
**/*.cs)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 Glob 来清点项目中的所有 C# 文件。
Glob: Assets/**/*.cs
分析:
.cs 文件总数wc -l)Plugins/、ThirdParty/、TextMesh Pro/ 文件夹(外部代码)用于统计所有文件行数的 Bash 命令:
find <project>/Assets -name "*.cs" -not -path "*/Plugins/*" -not -path "*/ThirdParty/*" -not -path "*/TextMesh Pro/*" | xargs wc -l | sort -rn | head -20
生成摘要:
## 项目结构
- **C# 文件** : 47
- **总行数** : 12,340
- **大于 500 行的文件** : PlayerManager.cs (623), GameController.cs (891)
- **主要文件夹** : Scripts/ (28), UI/ (12), Enemies/ (7)
扫描 C# 文件以查找 CPU、GPU 和内存反模式。完整检测模式表请参见 references/anti-patterns.md。
对于每个匹配项,记录文件、行号和代码行。在所有项目 .cs 文件上执行 Grep 搜索(排除项除外)。
为每个文件和全局分配分数:
| 严重性 | 分值 | 影响 |
|---|---|---|
| 严重 | 10 | 导致明显卡顿的直接原因(每帧) |
| 高 | 5 | 负载下性能显著下降 |
| 中 | 2 | 在性能分析器中可测量的影响 |
| 低 | 1 | 良好实践,影响最小 |
全局分数:
只对代码中实际发现的问题进行评分。切勿虚构假设性问题。
报告格式:包含 #、问题、严重性、文件:行号、描述 列的表格。按严重性分组(严重 > 高 > 中 > 低)。添加按严重性分类的摘要(数量 + 分数)。包含带有结论(良好 / 可接受 / 有问题 / 严重)的全局分数。
对于每个修复项,展示修复前后的代码。按严重性顺序处理问题(严重优先)。格式:标题、严重性、行号、影响,然后是修复前后的代码。
常见修复模式:
| 反模式 | 标准修复 |
|---|---|
| Update 中的 GetComponent | 在 Awake 中缓存到私有字段 |
| 运行时 Find | 在 Awake 中缓存或通过 SerializeField 注入 |
| Update 中的 Camera.main | private Camera _cam; void Awake() => _cam = Camera.main; |
| Update 中的字符串拼接 | StringBuilder 或 string.Format 或移除日志 |
| Update 中的 Instantiate | 对象池(Queue + 激活/停用) |
| Update 中的 foreach | 使用 List<T> 的 for 循环 |
| SendMessage | 直接接口或 C# 事件 |
| .tag == | .CompareTag("name") |
| 重复的 new WaitForSeconds | 缓存为 static readonly WaitForSeconds |
| 事件未取消订阅 | 在 OnDisable() 或 OnDestroy() 中添加 -= |
| Resources.Load 未卸载 | 使用后添加 Resources.UnloadUnusedAssets() 或切换到 Addressables |
必须遵守:
Start() 中的 GetComponent 是可接受的,Update() 中的则不是禁止:
foreach 报告为问题/unity-debug (Unity Debug)/unity-refactor (Unity Refactor)/unity-test (Unity Test)| 问题 | 解决方案 |
|---|---|
| GetComponent 误报过多 | 检查包围方法。Awake/Start/OnEnable 中的 GetComponent 不是问题。在 Grep 中使用 -B 20 查看上下文。 |
| 在注释中检测到模式 | 过滤以 // 开头或在 /* */ 块中的行。读取文件以确认。 |
| 文件太大无法分析 | 使用偏移/限制分块读取。专注于 Update、FixedUpdate、LateUpdate 方法。 |
| 项目没有 Assets/ 文件夹 | 检查项目路径。请用户确认 Unity 项目的根目录。 |
| 原型项目分数非常高 | 结合上下文:原型不需要深度优化。提及问题但降低紧急性。 |
| 在已禁用的代码中存在反模式 | 检查是否有 #if / [System.Obsolete] / 表明是死代码的注释。不报告死代码。 |
| 未找到 .cs 文件 | 项目可能为空或脚本在包中。使用不带文件夹过滤器的 Glob **/*.cs 进行检查。 |
| 事件泄漏误报 | 检查模式:如果 += 在 OnEnable 中且 -= 在 OnDisable 中,则是正确的。同时检查匿名 lambda(无法取消订阅)。 |
完整反模式表:参见 references/anti-patterns.md
每周安装次数
–
代码仓库
GitHub 星标数
3
首次出现时间
–
安全审计
Analyse statique du code C# d'un projet Unity pour detecter les anti-patterns de performance. Pas besoin d'executer le jeu ni de profiler -- on scanne le code source avec Grep et Glob.
Produit :
Assets/Symptome rapporte ?
|
+-- FPS bas en general --> Lancer le scan complet (etapes 1-5)
+-- Spikes ponctuels / stuttering --> Focus CPU (anti-patterns C1-C12)
+-- Memoire qui grimpe / crashs OOM --> Focus Memory (anti-patterns M1-M7)
+-- Rendu lent, draw calls hauts --> Focus GPU (anti-patterns G1-G5)
+-- Pas de symptome precis (audit preventif) --> Scan complet
**/*.cs)Utiliser Glob pour inventorier tous les fichiers C# du projet.
Glob: Assets/**/*.cs
Analyser :
.cswc -l)Plugins/, ThirdParty/, TextMesh Pro/ de l'analyse (code externe)Commande Bash pour compter les lignes de tous les fichiers :
find <project>/Assets -name "*.cs" -not -path "*/Plugins/*" -not -path "*/ThirdParty/*" -not -path "*/TextMesh Pro/*" | xargs wc -l | sort -rn | head -20
Produire un resume :
## Structure projet
- **Fichiers C#** : 47
- **Lignes totales** : 12,340
- **Fichiers > 500 lignes** : PlayerManager.cs (623), GameController.cs (891)
- **Dossiers principaux** : Scripts/ (28), UI/ (12), Enemies/ (7)
Scanner les fichiers C# pour les anti-patterns CPU, GPU et memoire. Voir references/anti-patterns.md pour la table complete des patterns a detecter.
Pour chaque match, noter le fichier, le numero de ligne, et la ligne de code. Executer les recherches Grep sur tous les fichiers .cs du projet (hors exclusions).
Attribuer un score par fichier et global :
| Severite | Points | Impact |
|---|---|---|
| Critical | 10 | Cause directe de lag visible (chaque frame) |
| High | 5 | Degradation significative sous charge |
| Medium | 2 | Impact mesurable au profiler |
| Low | 1 | Bonne pratique, impact minimal |
Score global :
Ne scorer que les problemes reellement trouves dans le code. Ne jamais inventer de problemes hypothetiques.
Format du rapport : tableau avec colonnes #, Probleme, Severite, Fichier:Ligne, Description. Grouper par severite (Critical > High > Medium > Low). Ajouter un resume par severite (nombre + score). Inclure un score global avec le verdict (Propre / Acceptable / Problematique / Critique).
Pour chaque fix, montrer le code avant et apres. Prendre les problemes par ordre de severite (Critical d'abord). Format : titre, severite, ligne, impact, puis code avant/apres.
Patterns de fix courants :
| Anti-pattern | Fix standard |
|---|---|
| GetComponent dans Update | Cache dans Awake avec champ prive |
| Find en runtime | Cache dans Awake ou injecter via SerializeField |
| Camera.main dans Update | private Camera _cam; void Awake() => _cam = Camera.main; |
| String concat dans Update | StringBuilder ou string.Format ou supprimer le log |
| Instantiate dans Update | Object pooling (Queue + activation/desactivation) |
| foreach dans Update | Boucle for avec List<T> |
TOUJOURS :
GetComponent dans Start() est acceptable, dans Update() nonJAMAIS :
foreach sur une collection fixe hors hot path comme un probleme/unity-debug (Unity Debug)/unity-refactor (Unity Refactor)/unity-test (Unity Test)| Probleme | Solution |
|---|---|
| Trop de faux positifs GetComponent | Verifier la methode englobante. GetComponent dans Awake/Start/OnEnable n'est pas un probleme. Utiliser -B 20 dans Grep pour voir le contexte. |
| Pattern detecte dans un commentaire | Filtrer les lignes qui commencent par // ou sont dans un bloc /* */. Lire le fichier pour confirmer. |
| Fichier trop gros pour analyser | Lire par sections avec offset/limit. Se concentrer sur les methodes Update, FixedUpdate, LateUpdate. |
Table complete des anti-patterns : voir references/anti-patterns.md
Weekly Installs
–
Repository
GitHub Stars
3
First Seen
–
Security Audits
TanStack Query v5 完全指南:React 数据管理、乐观更新、离线支持
2,500 周安装
| SendMessage |
| Interface directe ou event C# |
| .tag == | .CompareTag("name") |
| new WaitForSeconds repete | Cache static readonly WaitForSeconds |
| Event sans unsubscribe | Ajouter -= dans OnDisable() ou OnDestroy() |
| Resources.Load sans Unload | Ajouter Resources.UnloadUnusedAssets() apres usage ou passer a Addressables |
| Le projet n'a pas de dossier Assets/ |
| Verifier le path du projet. Demander a l'utilisateur de confirmer la racine du projet Unity. |
| Score tres eleve sur un prototype | Contextualiser : un prototype n'a pas besoin d'optimisation poussee. Mentionner les problemes mais reduire l'urgence. |
| Anti-pattern dans du code desactive | Verifier s'il y a #if / [System.Obsolete] / commentaire indiquant du code mort. Ne pas reporter le code mort. |
| Pas de fichiers .cs trouves | Le projet est peut-etre vide ou les scripts sont dans un package. Verifier avec Glob **/*.cs sans filtre de dossier. |
| Event leak faux positif | Verifier les patterns : si += est dans OnEnable et -= est dans OnDisable, c'est correct. Verifier aussi les lambdas anonymes (impossible a unsubscribe). |