besty0728/unity-batch
Unified batch and async-job orchestration — batch queries, preview-confirm-execute mutations, background job scheduling and polling, and bulk scene operations. Use when an operation touches many objects at once, running or polling long async jobs, or applying preview-then-commit bulk edits, even if the user just says "批量" or "一次性改很多". 统一的批量与异步任务编排(批量查询、预览-确认-执行变更、后台任务调度与轮询、批量场景操作);当用户要一次性操作大量对象、运行或轮询长时异步任务、或执行先预览后提交的批量编辑时使用。
npx skills add https://github.com/Besty0728/Unity-Skills --skill unity-batch
Batch workflow orchestration for query, preview, execution, reports, and async jobs.
本模块共 22 个 skill,按 Operation 区分为两类:
batch_query_gameobjects / batch_query_components / batch_query_assets / batch_preview_rename / batch_preview_set_property / batch_preview_replace_material / batch_report_get / batch_report_list / job_status / job_progress / job_logs / job_list / batch_fix_missing_scripts / batch_standardize_naming / batch_set_render_layer / batch_replace_material / batch_validate_scene_objects / batch_cleanup_temp_objects。Approval 模式下可直接执行。Mode 走默认 SkillMode.FullAuto):batch_execute / job_wait / job_cancel / batch_retry_failed。Approval 模式下首次调用返 MODE_RESTRICTED,走 grant 协议。> 注意:batch_execute(confirmToken) 本身放行,但它执行的 preview 内容可能包括对场景对象的删除/改属性等高影响动作 —— 请确保 batch_preview_* 返回的 sample/risk 字段已审阅。confirmToken 一次性消费、过期需重新 preview。
DO NOT (common hallucinations):
batch_preview_* skill first — batch_execute requires a confirmToken from a preview, it cannot be called directlybatch_run does not exist → use batch_execute(confirmToken)job_poll / job_result do not exist → use job_status to check and retrieve async job resultsbatch_delete / batch_move do not exist → use asset module for asset-level operationsRouting:
asset moduleworkflow modulebatch_validate_scene_objects (this module)job_status / job_wait (this module)Query GameObjects with unified batch filters. queryJson supports name/path/instanceId/tag/layer/active/componentType/sceneName/parentPath/prefabSource/includeInactive/limit.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| sampleLimit | int | No | 20 | Max sample objects returned |
Query components with unified batch filters. Optional componentType narrows the result.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| componentType | string | No | null | Optional component type constraint |
| sampleLimit | int | No | 20 | Max sample objects returned |
Query project assets by type, path pattern, and labels. Read-only.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| searchFilter | string | No | null | Raw Unity AssetDatabase filter string |
| folder | string | No | "Assets" | Search root folder |
| typeFilter | string | No | null | Asset type (prefix t: optional, e.g. Texture2D) |
| namePattern | string | No | null | Case-insensitive regex for filename |
| labelFilter | string | No | null | Asset label (prefix l: optional) |
| maxResults | int | No | 200 | Max results returned |
Preview batch renaming. mode supports prefix / suffix / replace / regex_replace.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| mode | string | No | "prefix" | Rename mode |
| prefix | string | No | null | Prefix to add |
| suffix | string | No | null | Suffix to add |
| search | string | No | null | Plain text search term |
| replacement | string | No | null | Plain text replacement |
| regexPattern | string | No | null | Regex search pattern |
| regexReplacement | string | No | null | Regex replacement text |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Preview setting a component property or field across queried targets.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| componentType | string | No | null | Target component type |
| propertyName | string | No | null | Property or field name |
| value | string | No | null | Literal value |
| referencePath | string | No | null | Scene reference path |
| referenceName | string | No | null | Scene reference object name |
| assetPath | string | No | null | Asset reference path |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Preview replacing Renderer materials across queried targets.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| materialPath | string | No | null | Replacement material asset path |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Execute a previously previewed batch operation by confirmToken. Large operations return a jobId.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| confirmToken | string | Yes | - | Preview confirmation token |
| runAsync | bool | No | true | Run as async job |
| chunkSize | int | No | 100 | Batch execution chunk size |
| progressGranularity | int | No | 10 | Emit a progressEvent every N items processed |
Get a batch execution report by reportId.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| reportId | string | Yes | - | Batch report identifier |
List recent batch reports.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| limit | int | No | 20 | Max reports returned |
Get status for an asynchronous UnitySkills job.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| jobId | string | Yes | - | Job identifier |
Get fine-grained progress events for a job via incremental polling. Use offset to fetch only new events since the last call (pass previous totalCount as next offset).
> Note: Also exposed as HTTP GET /jobs/{id}/progress and Python client.get_job_progress(job_id, offset) — all three paths share the same response shape.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| jobId | string | Yes | - | Job identifier |
| offset | int | No | 0 | Skip first N events (use previous totalCount for incremental polling) |
Response fields: jobId, status, totalCount, offset, events[] (timestamp ms, progress, stage, description), terminal.
Get structured logs for a UnitySkills job.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| jobId | string | Yes | - | Job identifier |
| limit | int | No | 100 | Max log entries returned |
List recent UnitySkills jobs.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| limit | int | No | 20 | Max jobs returned |
Wait for a UnitySkills job to finish or until timeoutMs elapses. Blocks the Unity main thread while waiting, so timeoutMs is clamped server-side to [0, 2000] regardless of the value you pass — a 10000/60000 request will actually wait at most 2s.
For job kinds whose progress depends on Unity's own engine loop rather than this plugin's own pump (compile, package, test, playmode, play_capture, build_player), blocking this thread cannot make them advance — Unity's compiler/domain-reload, PackageManager Request resolution, TestRunner callbacks, PlayMode state machine, and BuildPipeline all need the main thread free to tick. For those kinds job_wait does not enter a wait loop: it returns the current snapshot immediately with waitNotSupported: true and a hint pointing at the non-blocking alternatives below. Self-driven kinds (batch executor jobs such as rename / set_property / replace_material / set_render_layer / cleanup_temp_objects / fix_missing_scripts / standardize_naming, and test_smoke) still block up to the clamped timeout since each job_wait tick genuinely advances their state.
Recommended pattern for compile/package/test/playmode/play_capture/build_player jobs: poll GET /jobs/{id} (served off the HTTP thread, safe to call every 200-500ms) or long-poll GET /events — neither goes through the main-thread skill queue, so they stay responsive even while a job is mid-flight.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| jobId | string | Yes | - | Job identifier |
| timeoutMs | int | No | 10000 | Wait timeout in milliseconds; clamped to [0, 2000] |
Response adds terminal (bool) and waitNotSupported (bool) to the fields listed under job_status; hint is populated only when waitNotSupported is true.
Cancel a UnitySkills job if the job supports cancellation.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| jobId | string | Yes | - | Job identifier |
Preview batch removal of missing scripts. Execute with batch_execute(confirmToken).
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Preview standardizing names by trimming whitespace and normalizing separators. Execute with batch_execute(confirmToken).
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| separator | string | No | "_" | Replacement separator |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Preview setting GameObject layers in batch. Execute with batch_execute(confirmToken).
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| layer | string | No | null | Target layer name |
| recursive | bool | No | false | Apply recursively to children |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Preview replacing materials in batch. Execute with batch_execute(confirmToken).
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| materialPath | string | No | null | Replacement material asset path |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Analyze scene objects for missing scripts, missing references, duplicate names, and empty objects.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| issueLimit | int | No | 100 | Max issues returned |
Preview deleting temporary helper objects by common temp-name patterns. Execute with batch_execute(confirmToken).
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| queryJson | string | No | null | JSON query filter envelope |
| patternsCsv | string | No | null | Comma-separated temp-name patterns |
| sampleLimit | int | No | DefaultSampleLimit | Max preview items |
Re-run only the failed items from a previous batch execution report. Returns a new jobId and originalReportId.
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| reportId | string | Yes | — | Prior batch report ID to resume from |
| runAsync | bool | No | true | Whether to run asynchronously (returns jobId) |
| chunkSize | int | No | 100 | Chunk size per retry batch |
Exact names, parameters, defaults, and returns are defined by GET /skills/schema or unity_skills.get_skill_schema(), not by this file.
Take besty0728/unity-batch from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.