关于 unity-cleaner
unity-cleaner 是面向 Unity 项目的资源审计与清理技能集,可帮助开发者查找未使用、重复或异常资源。它提供依赖与引用分析,并对删除操作设置确认流程。
主要功能
- 01查找未使用资源和重复文件
- 02定位缺失引用与脚本
- 03检查资源使用情况和依赖树
- 04列出空文件夹及大型资源
- 05通过确认令牌删除资源
适用场景
- 01发布前审计 Unity 项目
- 02排查未使用或重复资源
- 03追踪资源依赖与引用
- 04清理缺失脚本组件
MCP 相关
作为技能模块,它向 MCP 工作流提供 Unity 资源查找、分析及清理操作;部分删除操作带有安全限制和确认步骤。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ besty0728/ unity-skills --skill unity-cleaner安装后在 Claude Code 中输入/unity-cleaner确认已加载。
详细介绍
**调用此模块中的任何技能之前:**如果你打算根据技能名称或描述猜测参数后调用技能,请停止——先阅读此文件(或通过
GET /skills/recommend?includeSchema=true获取其架构)。如果你已经从 recommend/schema 获得参数定义,则可以直接进行 dryRun。
触发条件
- 精简项目
- 排查重复或孤立资源
- 发布前审计
- 给项目瘦身、排查重复或孤立资源、发布前审计
Unity Cleaner 技能
安全性:
cleaner_delete_assets使用两步 confirmToken 握手。调用时不提供confirmToken可预览;再次调用并传入返回的令牌(有效期 5 分钟)即可实际删除。此操作没有dryRun参数。
防护措施
运行模式(v1.9 三级):
- Approval(默认):所有分析/查询技能(
cleaner_find_unused_assets、cleaner_find_duplicates、cleaner_find_missing_references、cleaner_get_asset_usage、cleaner_find_empty_folders、cleaner_find_large_assets、cleaner_get_dependency_tree)均为 SemiAuto,可直接运行。 - Auto / Bypass:SemiAuto 和 FullAuto 技能均可直接运行。
- 本模块中禁止 Auto 模式调用:
cleaner_delete_assets、cleaner_delete_empty_folders(两者都带有SkillOperation.Delete)。在 Approval/Auto 模式下,这些技能会返回MODE_FORBIDDEN——只有在 Bypass 模式下或通过用户管理的 Allowlist 条目才能调用;授权流程无法解锁它们。 cleaner_fix_missing_scripts是Execute | Modify操作(会原地将缺失的组件引用替换为 null,不会删除资源),因此不会触发 NeverInSemi 门控。在 Auto / Bypass 模式下可直接运行;在 Approval 模式下,执行前仍需完成标准授权握手。- 即使模式门控允许调用,
cleaner_delete_assets还会使用两步confirmToken握手——先预览(不提供令牌),再使用返回的令牌确认(有效期 5 分钟)。
不要(常见幻觉):
cleaner_delete/cleaner_remove不存在 → Cleaner 技能只负责查找/报告;实际删除请使用asset_deletecleaner_fix不存在 → 修复缺失脚本引用时,请专门使用cleaner_fix_missing_scriptscleaner_scan/cleaner_find_unused不存在 → 请使用具体技能:cleaner_find_unused_assets、cleaner_find_duplicates、cleaner_find_missing_references、cleaner_find_empty_folders、cleaner_find_large_assets
路由:
- 删除找到的资源 → 使用
asset模块中的asset_delete/asset_delete_batch - 验证项目 → 使用
validation模块
技能概览
| 技能 | 描述 |
|---|---|
cleaner_find_unused_assets | 查找未被其他资源引用的资源 |
cleaner_find_duplicates | 根据内容哈希查找重复文件 |
cleaner_find_missing_references | 查找缺失的脚本/资源引用 |
cleaner_delete_assets | 通过两步 confirmToken(预览 → 确认)删除资源 |
cleaner_get_asset_usage | 查找引用特定资源的内容 |
cleaner_find_empty_folders | 查找项目中的空文件夹 |
cleaner_find_large_assets | 按文件大小查找最大的资源 |
cleaner_delete_empty_folders | 删除所有空文件夹 |
cleaner_fix_missing_scripts | 从 GameObject 中移除缺失的脚本组件 |
cleaner_get_dependency_tree | 获取资源的依赖关系树 |
技能
cleaner_find_unused_assets
查找特定类型中可能未使用的资源。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
assetType | string | 否 | "Material" | 资源类型筛选条件 |
searchPath | string | 否 | "Assets" | 搜索路径 |
limit | int | 否 | 100 | 结果数量上限 |
返回值:{success, assetType, potentiallyUnusedCount, assets: [{path, name, type, sizeBytes}]}
# Find unused materials
result = call_skill("cleaner_find_unused_assets", assetType="Material")
# Find unused textures in a specific folder
result = call_skill("cleaner_find_unused_assets",
assetType="Texture2D", searchPath="Assets/Textures")
cleaner_find_duplicates
通过 MD5 哈希查找重复文件。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
assetType | string | 否 | "Texture2D" | 资源类型 |
searchPath | string | 否 | "Assets" | 搜索路径 |
limit | int | 否 | 50 | 最大分组数 |
返回:{success, duplicateGroupCount, totalWastedBytes, totalWastedMB, groups: [{count, sizeBytes, wastedBytes, files}], skipped: [{path, reason}]} — skipped 列出无法读取以进行哈希计算的文件,避免它们在分组中无声遗漏。
# Find duplicate textures
result = call_skill("cleaner_find_duplicates", assetType="Texture2D")
print(f"Wasted space: {result['totalWastedMB']:.2f} MB")
cleaner_find_missing_references
查找包含缺失脚本或空引用的组件。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
includeInactive | bool | 否 | true | 包含非活动对象 |
返回:{success, issueCount, missingScripts, missingReferences, issues: [{type, gameObject, path, ...}]}
# Scan for all missing references
result = call_skill("cleaner_find_missing_references")
print(f"Missing scripts: {result['missingScripts']}")
print(f"Missing references: {result['missingReferences']}")
cleaner_delete_assets
删除指定资源,需两步确认。
⚠️ 安全第一:删除需要调用两次——先预览,再确认。
步骤 1 - 预览(不提供 confirmToken):
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
paths | string[] | 否* | 要删除的资源路径 |
*此预览步骤必须提供;步骤 2 中省略该参数,步骤 2 会准确删除 confirmToken 已记录的路径。
返回:{success, action: "preview", totalAssets, existingAssets, totalBytes, totalMB, confirmToken, message, expiresIn, assetsToDelete: [{path, exists, sizeBytes, sizeMB}]}
步骤 2 - 确认(提供 confirmToken):
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
confirmToken | string | 是 | 预览步骤返回的令牌 |
返回:{success, action: "deleted", deletedCount, totalMB, message, results: [{path, deleted}]}
# Step 1: Preview what will be deleted
preview = call_skill("cleaner_delete_assets",
paths=["Assets/Unused/mat1.mat", "Assets/Unused/mat2.mat"])
print(preview['message']) # Shows: "⚠️ PREVIEW ONLY - 2 assets will be deleted..."
print(preview['assetsToDelete']) # Full list with sizes
# Step 2: Confirm deletion using token (expires in 5 minutes)
if input("Proceed? (y/n): ") == 'y':
result = call_skill("cleaner_delete_assets",
confirmToken=preview['confirmToken'])
print(result['message']) # "Successfully deleted 2 assets"
cleaner_get_asset_usage
查找引用特定资源的对象。
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
assetPath | string | 是 | 资源路径 |
limit | int | 否 | 最大结果数(默认 50) |
返回:{success, asset, usedByCount, usedBy: [{path, name, type}]}
# Check what uses a texture
result = call_skill("cleaner_get_asset_usage",
assetPath="Assets/Textures/player.png")
cleaner_find_empty_folders
查找项目中的空文件夹。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
searchPath | string | 否 | "Assets" | 搜索路径 |
返回: { success, count, folders }
# Find empty folders
result = call_skill("cleaner_find_empty_folders")
print(f"Found {result['count']} empty folders")
cleaner_find_large_assets
按文件大小查找最大的资源。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
searchPath | string | 否 | "Assets" | 搜索路径 |
limit | int | 否 | 20 | 最大结果数 |
minSizeBytes | long | 否 | 0 | 最小文件大小(字节) |
返回: { success, count, assets: [{ path, sizeBytes, sizeMB }] }
# Find top 10 largest assets over 1 MB
result = call_skill("cleaner_find_large_assets", limit=10, minSizeBytes=1048576)
for a in result['assets']:
print(f"{a['sizeMB']:.2f} MB - {a['path']}")
cleaner_delete_empty_folders
删除所有空文件夹。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
searchPath | string | 否 | "Assets" | 搜索路径 |
返回: { success, deleted, total }
# Delete all empty folders
result = call_skill("cleaner_delete_empty_folders")
print(f"Deleted {result['deleted']} of {result['total']} empty folders")
cleaner_fix_missing_scripts
从 GameObject 中移除缺失的脚本组件。
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
includeInactive | bool | 否 | true | 包含非活动对象 |
返回: { success, removedComponents }
# Remove all missing script components
result = call_skill("cleaner_fix_missing_scripts")
print(f"Removed {result['removedComponents']} missing script components")
cleaner_get_dependency_tree
获取资源的依赖关系树。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
assetPath | string | 是 | - | 资源路径 |
recursive | bool | 否 | true | 递归解析依赖项 |
返回: { success, assetPath, dependencyCount, dependencies: [{ path, type }] }
# Get full dependency tree for a prefab
result = call_skill("cleaner_get_dependency_tree",
assetPath="Assets/Prefabs/Player.prefab")
print(f"Dependencies: {result['dependencyCount']}")
示例工作流:清理项目
import unity_skills
# 1. Find all missing references and fix them
missing = unity_skills.call_skill("cleaner_find_missing_references")
for issue in missing['issues']:
if issue['type'] == 'MissingScript':
print(f"⚠️ Missing script on: {issue['path']}")
# 2. Find duplicate textures
dupes = unity_skills.call_skill("cleaner_find_duplicates", assetType="Texture2D")
if dupes['totalWastedMB'] > 10:
print(f"🗑️ {dupes['totalWastedMB']:.1f} MB wasted on duplicates")
# 3. Find unused materials
unused = unity_skills.call_skill("cleaner_find_unused_assets", assetType="Material")
print(f"📦 {unused['potentiallyUnusedCount']} potentially unused materials")
# 4. Preview cleanup
paths_to_delete = [a['path'] for a in unused['assets'][:5]]
preview = unity_skills.call_skill("cleaner_delete_assets",
paths=paths_to_delete)
print(f"Would free: {preview['totalMB']:.2f} MB")
# To actually delete, call again with preview['confirmToken'] within 5 minutes.
精确签名
确切的名称、参数、默认值和返回值由 GET /skills/schema 或 unity_skills.get_skill_schema() 定义,而非由此文件定义。