Add Unity Pipeline package support
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
* [Home](index.md)
|
||||
* Guides
|
||||
* [Creating commands](creating-commands.md)
|
||||
* [Creating authoring commands](authoring-commands.md)
|
||||
* [Safety & mutations](safety-and-mutations.md)
|
||||
* [Connectivity](connectivity.md)
|
||||
* [Runtime connection & setup](runtime-setup.md)
|
||||
* [Hot reload](hot-reload.md)
|
||||
* [Tests architecture](testing.md)
|
||||
* Command reference
|
||||
* [Asset & file commands](commands/assets-and-files.md)
|
||||
* [Scene commands](commands/scenes.md)
|
||||
* [GameObject & component commands](commands/gameobjects-and-components.md)
|
||||
* [Prefab commands](commands/prefabs.md)
|
||||
* [Script commands](commands/scripts.md)
|
||||
* [Animation commands](commands/animation.md)
|
||||
* [Material & shader commands](commands/materials.md)
|
||||
* [Baking commands](commands/baking.md)
|
||||
* [Navigation & selection commands](commands/navigation.md)
|
||||
* [Capture commands](commands/capture.md)
|
||||
* [Build, compilation & test commands](commands/build-and-compilation.md)
|
||||
* [Project settings commands](commands/project-settings.md)
|
||||
* [Package Manager commands](commands/package-manager.md)
|
||||
* [Editor lifecycle & observability commands](commands/editor-lifecycle-and-observability.md)
|
||||
* [Runtime commands](commands/runtime.md)
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
# Creating authoring commands
|
||||
|
||||
*Authoring commands* are the subset of commands that **create or mutate project content** — assets,
|
||||
scenes, GameObjects, components — on behalf of an agent. They build on the base command API in
|
||||
[Creating commands](creating-commands.md); this page covers the four concerns that are specific to
|
||||
content authoring:
|
||||
|
||||
- **The authoring root** — the sandbox that bare paths resolve against and writes are confined to.
|
||||
- **`ObjectRef`** — how a command *receives* a reference to an existing object.
|
||||
- **`AuthoringResult`** — how a command *returns* the identity of an object it created or touched.
|
||||
- **Undo/redo** — grouping a command's scene mutations into a single, revertible step.
|
||||
|
||||
Together these let one command's output feed the next command's input, so an agent can chain calls
|
||||
(`create_gameobject` → `add_component` → `set_component_properties` → `create_prefab`) without ever
|
||||
handling a raw Unity object itself. If you want to support a content type the package doesn't cover
|
||||
yet (materials, audio, lighting, terrain, …), this is the pattern to follow.
|
||||
|
||||
Read [Creating commands](creating-commands.md) first — this page assumes you know how `[CliCommand]`,
|
||||
`[CliArg]`, `MainThreadRequired`, and the response envelope work.
|
||||
|
||||
## Authoring vs. management commands
|
||||
|
||||
Not every state-changing command is an *authoring* command. This page — and the [checklist](#checklist-for-a-new-authoring-command)
|
||||
at the end — applies to commands that **create or mutate project content** (assets, scenes,
|
||||
GameObjects, components) and hand the agent back an object identity.
|
||||
|
||||
**Management commands** change *configuration* or *drive tooling* rather than author content:
|
||||
project settings (`Editor/Commands/ProjectSettings/`), builds (`Build/`), and packages
|
||||
(`PackageManager/`). They are a **different category** and deliberately do
|
||||
**not** follow the full authoring contract. They share only the cross-cutting safety conventions
|
||||
(the `confirm`/`dry_run` gate and, where relevant, `ObjectResolver`/`ProjectPaths`) — see
|
||||
[Safety & mutations](safety-and-mutations.md).
|
||||
|
||||
| Concern | Authoring command | Management command |
|
||||
|---|---|---|
|
||||
| Object input | `ObjectRef` → `ObjectResolver.TryResolve` | same, when it references an object (e.g. a scene in the build list) |
|
||||
| Path input | `ProjectPaths.Resolve` (confined to the authoring root) | as needed; may be unconfined by design (e.g. a build output path) |
|
||||
| Undo | scene/object mutations wrapped in `AuthoringUndoScope` + registered `Undo` APIs | **none** — settings / AssetDatabase / UPM writes don't participate in Undo, so no scope; note `Not undoable via Ctrl+Z.` in the description instead |
|
||||
| Destructive gate | `confirm`/`dry_run` where destructive | `confirm`/`dry_run` where destructive (same convention) |
|
||||
| Return value | `AuthoringResult` via `ObjectResolver.Describe` | a domain model (e.g. `ProjectSettingsResponse`, `PackageMutationResponse`) or a plain result object |
|
||||
| Failure | **throw** (`ArgumentException` / `InvalidOperationException`) | throw, **or** return a structured `{ success = false, code, error }` object — consistent within the area |
|
||||
|
||||
If you're adding a config/build/package command, follow the management column and the shared safety
|
||||
conventions; the checklist below is for content-authoring commands.
|
||||
|
||||
## The building blocks
|
||||
|
||||
| Type | Namespace | Role |
|
||||
|------|-----------|------|
|
||||
| `ProjectPaths` | `Unity.Pipeline.Editor.Authoring` | Resolve/confine agent-supplied paths to the authoring root. |
|
||||
| `ObjectRef` | `Unity.Pipeline.Models` | Input handle to an existing object (asset or scene object). |
|
||||
| `AuthoringResult` | `Unity.Pipeline.Models` | Output identity of an object your command created or acted on. |
|
||||
| `ObjectResolver` | `Unity.Pipeline.Editor.Authoring` | `TryResolve(ObjectRef …)` (handle → object) and `Describe(object)` (object → `AuthoringResult`). |
|
||||
| `AuthoringUndoScope` | `Unity.Pipeline.Editor.Authoring` | Collapses all `Undo`-registered mutations in its lifetime into one editor undo step. |
|
||||
|
||||
Authoring commands are Editor-only. Put them under `Editor/Commands/<Area>/` in the
|
||||
`Unity.Pipeline.Editor.Commands.<Area>` namespace (see `Editor/Commands/Authoring/AuthoringConfigCommands.cs`).
|
||||
|
||||
## The authoring root (`set_authoring_root`)
|
||||
|
||||
Agents pass **bare, relative paths** (`"Materials/Stone"`), not full project paths. `ProjectPaths`
|
||||
resolves those against a configurable **authoring root** and *confines* every write to it. The root
|
||||
defaults to `Assets` (full project access); an agent can narrow it to a sub-folder to sandbox itself:
|
||||
|
||||
```
|
||||
get_authoring_root → { "root": "Assets" }
|
||||
set_authoring_root --root Assets/AgentWork
|
||||
```
|
||||
|
||||
These are just thin commands over `ProjectPaths.AuthoringRoot` (`Editor/Commands/Authoring/AuthoringConfigCommands.cs`):
|
||||
|
||||
```csharp
|
||||
[CliCommand("set_authoring_root", "Set the base folder (under Assets/) that bare authoring paths resolve against and are confined to. Use 'Assets' for full project access.")]
|
||||
public static object SetAuthoringRoot(
|
||||
[CliArg("root", "Project-relative folder under Assets/, e.g. Assets/AgentWork. Use 'Assets' to allow the whole project.", Required = true)] string root)
|
||||
{
|
||||
// Throws ArgumentException for invalid roots (outside Assets/ or containing ".."); the
|
||||
// server surfaces that message to the caller.
|
||||
ProjectPaths.AuthoringRoot = root;
|
||||
return new { root = ProjectPaths.AuthoringRoot };
|
||||
}
|
||||
```
|
||||
|
||||
**Every path parameter your command accepts must go through `ProjectPaths.Resolve`.** This is the
|
||||
sandbox boundary — it rejects `..` traversal and anything that escapes the root, and it lets callers
|
||||
omit the `Assets/` prefix. Do not build asset paths by string concatenation.
|
||||
|
||||
```csharp
|
||||
var normalized = ProjectPaths.Resolve(path, out var error);
|
||||
if (normalized == null)
|
||||
throw new ArgumentException(error); // e.g. "Path '../secrets' must not contain '..'."
|
||||
// normalized is now a project-relative path guaranteed to live under the authoring root.
|
||||
```
|
||||
|
||||
Resolution rules (`Editor/Authoring/ProjectPaths.cs`):
|
||||
|
||||
- Bare paths (`"Materials/Stone"`) are taken relative to the root → `Assets/AgentWork/Materials/Stone`.
|
||||
- Explicit `Assets/…` / `Packages/…` paths are used as-is (but still confined to the root).
|
||||
- Absolute paths must live under the project root and are converted to project-relative.
|
||||
- `..` anywhere, or a result outside the root, returns `null` + an `error` string.
|
||||
|
||||
## Receiving objects: `ObjectRef`
|
||||
|
||||
When a command needs to act on an object that *already* exists, take an `ObjectRef` parameter. The
|
||||
agent supplies **one** of several forms; `ObjectResolver.TryResolve` tries them in order — `globalId`,
|
||||
`path`, `guid` (+ optional `fileId`), `instanceId`, `hierarchyPath` — and hands you the live object:
|
||||
|
||||
```csharp
|
||||
public static Renderer ResolveRenderer(ObjectRef target)
|
||||
{
|
||||
if (!ObjectResolver.TryResolve(target, out var obj, out var error))
|
||||
throw new ArgumentException(error);
|
||||
|
||||
var go = obj as GameObject ?? (obj as Component)?.gameObject;
|
||||
var renderer = go != null ? go.GetComponent<Renderer>() : null;
|
||||
if (renderer == null)
|
||||
throw new ArgumentException($"Object '{target}' has no Renderer.");
|
||||
return renderer;
|
||||
}
|
||||
```
|
||||
|
||||
Resolve **outside** any undo scope / before mutating, so a bad handle fails before your command
|
||||
changes anything (see `create_gameobject`, which resolves its `parent` before entering the scope).
|
||||
|
||||
When the handle is a plain string (the usual agent input), a value with a file extension and no
|
||||
leading `/` — e.g. `"Materials/Floor.mat"` — is taken as an asset path and normalized under the
|
||||
authoring root, so the `Assets/` prefix is optional (mirroring path-taking commands). A leading `/`
|
||||
or an extension-less value stays a `hierarchyPath`; a dotted scene name like `"Cube.001"` still
|
||||
resolves because the `path` branch falls back to a hierarchy lookup.
|
||||
|
||||
## Returning objects: `AuthoringResult`
|
||||
|
||||
Any command that creates or modifies an object should return its identity so the agent can reference
|
||||
it in a follow-up call. Don't build this by hand — call `ObjectResolver.Describe(obj)`, which fills in
|
||||
the right fields for the object kind:
|
||||
|
||||
- **Assets** get `assetPath`, `guid`, `fileId`, `type` (+ `globalId`).
|
||||
- **Scene / loaded objects** get `instanceId`, `hierarchyPath`, `type` (+ `globalId`).
|
||||
|
||||
```csharp
|
||||
var result = ObjectResolver.Describe(asset) ?? new AuthoringResult { Type = nameof(Material) };
|
||||
result.AssetPath = assetPath; // ensure the path is set even if Describe returned a fresh result
|
||||
return result;
|
||||
```
|
||||
|
||||
`AuthoringResult` is **identity only** — no success flag, no message. Success/failure and timing live
|
||||
in the outer `CommandExecutionResponse` (the server adds them). To report a failure, **throw**
|
||||
(`ArgumentException` for bad input, `InvalidOperationException` for an operation that failed); the
|
||||
server converts the exception into a failure envelope. For a batch, return a model that holds an
|
||||
`AuthoringResult[]` (see `CreateGameObjectsResult`).
|
||||
|
||||
## Undo/redo
|
||||
|
||||
Undo is Unity's native `UnityEditor.Undo`, grouped per command by `AuthoringUndoScope` so a single
|
||||
call reverts as a single Ctrl+Z step. Register each mutation with the matching `Undo` API **inside**
|
||||
the scope:
|
||||
|
||||
```csharp
|
||||
using (new AuthoringUndoScope("Set Material"))
|
||||
{
|
||||
Undo.RecordObject(renderer, "Set Material"); // record BEFORE mutating
|
||||
renderer.sharedMaterial = material;
|
||||
EditorSceneManager.MarkSceneDirty(renderer.gameObject.scene);
|
||||
}
|
||||
```
|
||||
|
||||
Which `Undo` call to use:
|
||||
|
||||
| Mutation | Call |
|
||||
|----------|------|
|
||||
| New scene object | `Undo.RegisterCreatedObjectUndo(obj, name)` |
|
||||
| Change fields on an existing object | `Undo.RecordObject(obj, name)` / `RegisterCompleteObjectUndo` (before the change) |
|
||||
| Add a component | `Undo.AddComponent(go, type)` |
|
||||
| Reparent | `Undo.SetTransformParent(child, parent, name)` |
|
||||
| Serialized properties | `SerializedObject` + `so.ApplyModifiedProperties()` (registers undo itself) |
|
||||
|
||||
> **Important caveat.** `AssetDatabase` operations are **not** part of Unity's undo system. Creating a
|
||||
> folder or asset, importing, `AssetDatabase.CreateAsset`, `SaveAsPrefabAsset`, and file writes are
|
||||
> **not undone** by Ctrl+Z. `AuthoringUndoScope` only covers scene/object mutations. If your command
|
||||
> writes to disk, say so in its description and don't rely on undo to clean up — validate up front and
|
||||
> fail before writing.
|
||||
|
||||
## Worked example — a new content type
|
||||
|
||||
Say the package has no material (rendering) commands and you want to add them. Two commands cover the
|
||||
whole pattern: one that **creates an asset** (path handling + `AuthoringResult` out, no undo because
|
||||
it's an `AssetDatabase` op) and one that **mutates a scene object** (`ObjectRef` in + undo).
|
||||
|
||||
```csharp
|
||||
using System.IO;
|
||||
using Unity.Pipeline.Commands;
|
||||
using Unity.Pipeline.Editor.Authoring;
|
||||
using Unity.Pipeline.Models;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Pipeline.Editor.Commands.Rendering
|
||||
{
|
||||
/// <summary>Authoring commands for materials (rendering).</summary>
|
||||
public static class MaterialCommands
|
||||
{
|
||||
[CliCommand("create_material",
|
||||
"Create a Material asset (default shader 'Standard') under the authoring root. " +
|
||||
"NOTE: asset creation is not undoable via Ctrl+Z.")]
|
||||
public static AuthoringResult CreateMaterial(
|
||||
[CliArg("path", "Asset path relative to the authoring root; the Assets/ prefix and the .mat extension are optional. e.g. Materials/Stone", Required = true)] string path,
|
||||
[CliArg("shader", "Shader name to assign. Defaults to 'Standard'.")] string shader = "Standard")
|
||||
{
|
||||
// 1. Resolve + confine the path (the sandbox boundary).
|
||||
var normalized = ProjectPaths.Resolve(path, out var error);
|
||||
if (normalized == null)
|
||||
throw new ArgumentException(error);
|
||||
if (!normalized.EndsWith(".mat", System.StringComparison.OrdinalIgnoreCase))
|
||||
normalized += ".mat";
|
||||
|
||||
var found = Shader.Find(shader);
|
||||
if (found == null)
|
||||
throw new ArgumentException($"Shader '{shader}' was not found.");
|
||||
|
||||
// 2. Do the work (AssetDatabase op — no undo scope; it wouldn't be undoable anyway).
|
||||
EnsureParentFolder(normalized);
|
||||
var material = new Material(found);
|
||||
AssetDatabase.CreateAsset(material, normalized);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
// 3. Return the created object's identity so the agent can reference it next.
|
||||
var result = ObjectResolver.Describe(material) ?? new AuthoringResult { Type = nameof(Material) };
|
||||
result.AssetPath = normalized;
|
||||
return result;
|
||||
}
|
||||
|
||||
[CliCommand("set_material", "Assign a material asset to a Renderer on a scene GameObject.")]
|
||||
public static AuthoringResult SetMaterial(
|
||||
[CliArg("target", "Handle of the GameObject (or Renderer) to modify.", Required = true)] ObjectRef target,
|
||||
[CliArg("material", "Handle of the material asset to assign (path/guid/globalId).", Required = true)] ObjectRef material)
|
||||
{
|
||||
// Resolve both handles up front, before mutating, so a bad handle changes nothing.
|
||||
var renderer = ResolveRenderer(target);
|
||||
if (!ObjectResolver.TryResolve(material, out var matObj, out var matError))
|
||||
throw new ArgumentException(matError);
|
||||
if (matObj is not Material mat)
|
||||
throw new ArgumentException($"'{material}' is not a Material.");
|
||||
|
||||
using (new AuthoringUndoScope("Set Material"))
|
||||
{
|
||||
Undo.RecordObject(renderer, "Set Material"); // record BEFORE the change
|
||||
renderer.sharedMaterial = mat;
|
||||
EditorSceneManager.MarkSceneDirty(renderer.gameObject.scene);
|
||||
}
|
||||
|
||||
return ObjectResolver.Describe(renderer);
|
||||
}
|
||||
|
||||
private static Renderer ResolveRenderer(ObjectRef target)
|
||||
{
|
||||
if (!ObjectResolver.TryResolve(target, out var obj, out var error))
|
||||
throw new ArgumentException(error);
|
||||
|
||||
var go = obj as GameObject ?? (obj as Component)?.gameObject;
|
||||
var renderer = go != null ? go.GetComponent<Renderer>() : null;
|
||||
if (renderer == null)
|
||||
throw new ArgumentException($"Object '{target}' has no Renderer.");
|
||||
return renderer;
|
||||
}
|
||||
|
||||
// Mirrors the shared helper used by the built-in asset commands.
|
||||
private static void EnsureParentFolder(string assetPath)
|
||||
{
|
||||
var parent = Path.GetDirectoryName(assetPath)?.Replace('\\', '/');
|
||||
if (string.IsNullOrEmpty(parent) || AssetDatabase.IsValidFolder(parent))
|
||||
return;
|
||||
// Create intermediate folders (see create_folder / CreateFolderRecursive).
|
||||
Directory.CreateDirectory(ProjectPaths.ProjectRoot + "/" + parent);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
An agent chains them by feeding the first result into the second:
|
||||
|
||||
```
|
||||
create_material --path Materials/Stone --shader Standard
|
||||
→ { "assetPath": "Assets/AgentWork/Materials/Stone.mat", "guid": "…", "type": "Material" }
|
||||
|
||||
set_material --target '{"hierarchyPath":"/Ground"}' --material '{"path":"Assets/AgentWork/Materials/Stone.mat"}'
|
||||
→ { "instanceId": …, "hierarchyPath": "/Ground", "type": "MeshRenderer" }
|
||||
```
|
||||
|
||||
## Checklist for a new authoring command
|
||||
|
||||
For *content-authoring* commands. Config/build/package commands follow the lighter
|
||||
[management-command conventions](#authoring-vs-management-commands) instead.
|
||||
|
||||
- [ ] Editor-only, under `Editor/Commands/<Area>/`, `static` (any accessibility — `public`/`internal`/`private`), tagged `[CliCommand]`.
|
||||
- [ ] Every path parameter resolved through `ProjectPaths.Resolve` (never concatenated).
|
||||
- [ ] Existing-object inputs taken as `ObjectRef`, resolved via `ObjectResolver.TryResolve`; resolve **before** mutating.
|
||||
- [ ] Scene/object mutations wrapped in an `AuthoringUndoScope` and registered with the matching `Undo` API.
|
||||
- [ ] `AssetDatabase` writes noted as non-undoable in the description; validate before writing.
|
||||
- [ ] Returns `AuthoringResult` (via `ObjectResolver.Describe`) or a model containing `AuthoringResult[]`.
|
||||
- [ ] Reports failures by throwing; never build the response envelope yourself.
|
||||
|
||||
## Build & verify
|
||||
|
||||
New commands register automatically after the next recompile (see
|
||||
[Creating commands → Discovery](creating-commands.md#discovery)). Drive the live editor to verify:
|
||||
|
||||
```
|
||||
command recompile
|
||||
command recompile_status # poll until done
|
||||
command create_material --path Materials/Stone
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Creating commands](creating-commands.md) — the base command API this page builds on.
|
||||
- [Asset & file commands](commands/assets-and-files.md) — reference for the built-in asset commands.
|
||||
- [GameObject & component commands](commands/gameobjects-and-components.md) — the scene-mutation commands.
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
# Animation commands
|
||||
|
||||
Author animation assets: AnimationClips (and their float curves), AnimatorControllers (parameters, layers, states, transitions), and Timeline assets. Create commands write under the authoring root and follow the shared `confirm`/`dry_run` convention.
|
||||
|
||||
## AnimationClips
|
||||
|
||||
### `create_animation_clip`
|
||||
Create an empty .anim AnimationClip asset under the authoring root, with an optional frame rate and loop flag.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | `–` | Asset path ending in .anim, relative to the authoring root. The Assets/ prefix is optional. |
|
||||
| `frameRate` | no | `60` | Sampling frame rate of the clip. |
|
||||
| `loop` | no | `false` | If true, set the clip's loop-time flag in its AnimationClipSettings. |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be created without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
|
||||
### `set_animation_curve`
|
||||
Add or replace a single float curve binding on an AnimationClip (via AnimationUtility.SetEditorCurve). Replacing an existing binding overwrites it rather than duplicating.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `clip` | yes | `–` | Reference to the AnimationClip to edit (path / guid / globalId). |
|
||||
| `path` | no | `""` | GameObject path relative to the animated root the property lives on. Empty string targets the root. |
|
||||
| `type` | yes | `–` | Component type the property lives on, e.g. "Transform", "UnityEngine.Light". Resolved via the component TypeResolver. |
|
||||
| `property` | yes | `–` | Curve property name, e.g. "m_LocalPosition.x", "m_LocalScale.y", "localEulerAnglesRaw.z". |
|
||||
| `keys` | yes | `–` | Keyframes: `[{ time, value, inTangent?, outTangent?, weightedMode?: "None"\|"In"\|"Out"\|"Both" }]`. Omitted tangents default to 0 (flat); this is NOT Unity's Auto tangent mode. |
|
||||
| `dry_run` | no | `false` | If true, validate type/property/keys without writing the curve. |
|
||||
|
||||
**Returns:** `SetAnimationCurveResult`
|
||||
|
||||
### `get_animation_clip`
|
||||
Read an AnimationClip's metadata and all float curve bindings (optionally with keyframes).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `clip` | yes | `–` | Reference to the AnimationClip to read (path / guid / globalId). |
|
||||
| `includeKeys` | no | `false` | If true, include each binding's keyframes. |
|
||||
|
||||
**Returns:** `AnimationClipInfo`
|
||||
|
||||
### `remove_animation_curve`
|
||||
Remove a float curve binding from an AnimationClip (SetEditorCurve(clip, binding, null)). Destructive: requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `clip` | yes | `–` | Reference to the AnimationClip to edit (path / guid / globalId). |
|
||||
| `path` | no | `""` | GameObject path relative to the animated root the binding lives on. Empty string targets the root. |
|
||||
| `type` | yes | `–` | Component type of the binding to remove, e.g. "Transform". Resolved via the component TypeResolver. |
|
||||
| `property` | yes | `–` | Curve property name to remove, e.g. "m_LocalPosition.x". |
|
||||
| `confirm` | no | `false` | Must be true to actually remove the binding (destructive guard). |
|
||||
| `dry_run` | no | `false` | If true, report the binding that would be removed without removing it. |
|
||||
|
||||
**Returns:** `SetAnimationCurveResult`
|
||||
|
||||
## AnimatorControllers
|
||||
|
||||
### `create_animator_controller`
|
||||
Create an .controller AnimatorController asset (with a default Base Layer) under the authoring root.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | `–` | Asset path ending in .controller, relative to the authoring root. The Assets/ prefix is optional. |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be created without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
|
||||
### `add_animator_parameter`
|
||||
Add a parameter (Float | Int | Bool | Trigger) to an AnimatorController. A duplicate name returns code 'duplicate_parameter'.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `controller` | yes | `–` | Reference to the AnimatorController to edit (path / guid / globalId). |
|
||||
| `name` | yes | `–` | Parameter name. |
|
||||
| `type` | yes | `–` | Parameter type: Float \| Int \| Bool \| Trigger. |
|
||||
| `defaultValue` | no | `–` | Default value for Float/Int/Bool (ignored for Trigger). |
|
||||
| `dry_run` | no | `false` | If true, validate inputs without writing the parameter. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `add_animator_layer`
|
||||
Add a layer to an AnimatorController.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `controller` | yes | `–` | Reference to the AnimatorController to edit (path / guid / globalId). |
|
||||
| `name` | yes | `–` | Layer name. |
|
||||
| `weight` | no | `1` | Layer weight. |
|
||||
| `blendingMode` | no | `Override` | Blending mode: Override \| Additive. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs without writing the layer. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `add_animator_state`
|
||||
Add a state to a layer, optionally with a motion (AnimationClip or BlendTree) and as the layer default. A layer name with no match returns code 'layer_not_found'.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `controller` | yes | `–` | Reference to the AnimatorController to edit (path / guid / globalId). |
|
||||
| `layer` | no | `0` | Layer index (int) or name (string). Default 0 (Base Layer). |
|
||||
| `name` | yes | `–` | State name. |
|
||||
| `motion` | no | `–` | Optional AnimationClip or BlendTree asset to assign as the state's motion. |
|
||||
| `isDefault` | no | `false` | If true, set this state as the layer's default state. |
|
||||
| `position` | no | `–` | Optional [x, y] node position in the graph (cosmetic). |
|
||||
| `dry_run` | no | `false` | If true, validate inputs without writing the state. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `add_animator_transition`
|
||||
Add a transition between two states (or from AnyState/Entry, to Exit) on a layer, with optional conditions. Validates that the states exist and each condition's parameter exists and its mode matches the parameter type.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `controller` | yes | `–` | Reference to the AnimatorController to edit (path / guid / globalId). |
|
||||
| `layer` | no | `0` | Layer index (int) or name (string). Default 0 (Base Layer). |
|
||||
| `fromState` | yes | `–` | Source state name, or the special "AnyState" / "Entry". |
|
||||
| `toState` | yes | `–` | Destination state name, or the special "Exit". |
|
||||
| `conditions` | no | `–` | Optional conditions: `[{ parameter, mode: "If"\|"IfNot"\|"Greater"\|"Less"\|"Equals"\|"NotEqual", threshold? }]`. |
|
||||
| `hasExitTime` | no | `false` | If true, the transition uses exit time. |
|
||||
| `exitTime` | no | `0` | Normalized exit time (0..1) when hasExitTime is set. |
|
||||
| `duration` | no | `0.25` | Transition duration in seconds. |
|
||||
| `hasFixedDuration` | no | `true` | If true, duration is in seconds; otherwise normalized. |
|
||||
| `dry_run` | no | `false` | If true, validate everything (states, parameters, mode/type) without writing the transition. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `get_animator_controller`
|
||||
Read an AnimatorController's full structure: parameters, layers, states (with motion / default), and transitions (with conditions).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `controller` | yes | `–` | Reference to the AnimatorController to read (path / guid / globalId). |
|
||||
|
||||
**Returns:** `AnimatorControllerInfo`
|
||||
|
||||
## Timeline
|
||||
|
||||
The Timeline commands require the `com.unity.timeline` package.
|
||||
|
||||
### `create_timeline`
|
||||
Create a .playable TimelineAsset under the authoring root (optional frame rate).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | `–` | Asset path ending in .playable, relative to the authoring root. The Assets/ prefix is optional. |
|
||||
| `frameRate` | no | `60` | Timeline frame rate. |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be created without writing anything. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `add_timeline_track`
|
||||
Add a track (Animation | Audio | Activation | Control | Playable | Signal | Marker) to a TimelineAsset, optionally nested under a parent group/track.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `timeline` | yes | `–` | Reference to the TimelineAsset to edit (path / guid / globalId). |
|
||||
| `trackType` | yes | `–` | Track type: Animation \| Audio \| Activation \| Control \| Playable \| Signal \| Marker. |
|
||||
| `name` | no | `–` | Optional track display name. |
|
||||
| `parentTrack` | no | `–` | Optional name of an existing group/track to nest the new track under. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs without writing the track. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `add_timeline_clip`
|
||||
Add a clip to a named track on a TimelineAsset. For Animation tracks pass an AnimationClip asset; for Audio tracks an AudioClip.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `timeline` | yes | `–` | Reference to the TimelineAsset to edit (path / guid / globalId). |
|
||||
| `track` | yes | `–` | Target track name. |
|
||||
| `start` | yes | `–` | Clip start time in seconds. |
|
||||
| `duration` | yes | `–` | Clip duration in seconds. |
|
||||
| `asset` | no | `–` | Source asset: for Animation tracks an AnimationClip; for Audio tracks an AudioClip. Required for those track types. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs without writing the clip. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `get_timeline`
|
||||
Read a TimelineAsset's structure: frame rate, duration, and its tracks with their clips.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `timeline` | yes | `–` | Reference to the TimelineAsset to read (path / guid / globalId). |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
# Asset & file commands
|
||||
|
||||
Commands for creating, importing, moving, copying, renaming, deleting and finding project assets, plus folder and text-file operations. Every agent-supplied path is funnelled through the authoring-root sandbox (it rejects `../` and out-of-project writes); destructive or overwriting operations require `confirm=true` and support `dry_run`. AssetDatabase create/move/copy/rename/delete are not part of Unity's Undo system.
|
||||
|
||||
### `create_asset`
|
||||
Create a new ScriptableObject (or other UnityEngine.Object) asset of the given type at a path under the authoring root.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Asset path relative to the authoring root, including extension (e.g. Data/Config.asset or Materials/Wall.mat). The Assets/ prefix is optional. |
|
||||
| `type` | yes | – | Fully-qualified or short type name to instantiate (e.g. UnityEngine.Material, MyGame.GameConfig). Must derive from UnityEngine.Object and be creatable. |
|
||||
| `shader` | no | `–` | Material-only (ignored otherwise): shader name to assign (e.g. Standard, "Universal Render Pipeline/Lit"). When omitted, defaults to "Universal Render Pipeline/Lit" if a Scriptable Render Pipeline is active, otherwise the built-in "Standard" shader (falling back to "Standard" if URP/Lit is unavailable). |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the path. Ignored when the path is empty. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be created without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** `confirm=true` required to overwrite an existing asset; supports `dry_run`.
|
||||
|
||||
### `import_asset`
|
||||
Import an external file (e.g. a texture, model, audio clip) into the project by copying it to a path under the authoring root, then importing it.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `source` | yes | – | Absolute filesystem path to the external file to import. |
|
||||
| `path` | yes | – | Destination asset path relative to the authoring root, including extension. The Assets/ prefix is optional. |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the destination path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be imported without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** `confirm=true` required to overwrite an existing asset; supports `dry_run`.
|
||||
|
||||
### `move_asset`
|
||||
Move (or rename via a new path) an asset to a new location under the authoring root. Preserves the asset's GUID.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset to move (path / guid / globalId). |
|
||||
| `destination` | yes | – | Destination asset path relative to the authoring root, including extension. The Assets/ prefix is optional. |
|
||||
| `dry_run` | no | `false` | If true, validate the move (via AssetDatabase.ValidateMoveAsset) without performing it. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Supports `dry_run`.
|
||||
|
||||
### `copy_asset`
|
||||
Copy an asset to a new path under the authoring root. The copy gets a fresh GUID.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset to copy (path / guid / globalId). |
|
||||
| `destination` | yes | – | Destination asset path relative to the authoring root, including extension. The Assets/ prefix is optional. |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing asset at the destination path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be copied without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** `confirm=true` required to overwrite an existing asset; supports `dry_run`.
|
||||
|
||||
### `rename_asset`
|
||||
Rename an asset in place (keeps it in the same folder, keeps its GUID).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset to rename (path / guid / globalId). |
|
||||
| `new_name` | yes | – | New file name WITHOUT a folder path. The extension is preserved if omitted. |
|
||||
| `dry_run` | no | `false` | If true, validate the rename without performing it. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Supports `dry_run`.
|
||||
|
||||
### `delete_asset`
|
||||
Delete an asset from the project. Destructive: requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset to delete (path / guid / globalId). |
|
||||
| `confirm` | no | `false` | Must be true to actually delete. Without it the command refuses (destructive guard). |
|
||||
| `dry_run` | no | `false` | If true, report the asset that would be deleted without deleting it. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Destructive — `confirm=true` required; supports `dry_run`. Not undoable via Unity's Undo.
|
||||
|
||||
### `find_assets`
|
||||
Find assets by type and/or name and/or label, returning their path, GUID and type. At least one filter is required.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `type` | no | `–` | Type name to filter by (e.g. Material, GameObject, ScriptableObject, MyGame.GameConfig). Resolved to a System.Type and matched against each asset's actual main type. |
|
||||
| `name` | no | `–` | Name substring to filter by (AssetDatabase name filter). |
|
||||
| `label` | no | `–` | Asset label to filter by (AssetDatabase 'l:' filter). |
|
||||
| `search_in` | no | `–` | Folder to scope the search to, relative to the authoring root (default: the authoring root). |
|
||||
| `limit` | no | `200` | Maximum number of results to return (default 200). |
|
||||
|
||||
**Returns:** `FindAssetsResult`
|
||||
**Notes:** At least one of `type`, `name`, or `label` is required.
|
||||
|
||||
### `set_import_settings`
|
||||
Set import settings on an asset's AssetImporter (e.g. a texture's isReadable) and re-import it.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset whose importer to edit (path / guid / globalId). |
|
||||
| `settings` | yes | – | JSON object of importer property/field names to values, e.g. {"isReadable": true, "textureType": "NormalMap"}. |
|
||||
| `dry_run` | no | `false` | If true, validate which settings would apply (and which are unknown) without writing or re-importing. |
|
||||
|
||||
**Returns:** `SetImportSettingsResult`
|
||||
**Notes:** Supports `dry_run`. Import settings live in the asset's .meta file and are not part of Unity's Undo system.
|
||||
|
||||
### `get_import_settings`
|
||||
Read an asset's import settings, structured by importer type (texture/model/audio), including the default-platform fields and (for textures/audio) one platform override block.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `asset` | yes | – | Reference to the asset whose importer to read (path / guid / globalId). |
|
||||
| `platform` | no | `Default` | Platform whose override to read: Default \| Standalone \| iOS \| Android \| WebGL \| tvOS. |
|
||||
|
||||
**Returns:** `GetImportSettingsResult`
|
||||
|
||||
### `create_folder`
|
||||
Create a folder under the authoring root (creates intermediate folders).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Folder path relative to the authoring root (default Assets/); the Assets/ prefix is optional. e.g. Gameplay/Enemies or Assets/Gameplay/Enemies |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
|
||||
### `read_text_file`
|
||||
Read a UTF-8 text file under the authoring root and return its contents.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Text file path relative to the authoring root. The Assets/ prefix is optional. |
|
||||
| `max_bytes` | no | `1048576` | Reject files larger than this many bytes (default 1048576 = 1 MiB) to avoid huge payloads. |
|
||||
|
||||
**Returns:** `ReadTextFileResult`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `write_text_file`
|
||||
Write UTF-8 text to a file under the authoring root, then import it. Overwriting an existing file requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Text file path relative to the authoring root, including extension. The Assets/ prefix is optional. |
|
||||
| `contents` | yes | – | The full text content to write (replaces the file). |
|
||||
| `confirm` | no | `false` | Required (true) only when overwriting an existing file at the path. |
|
||||
| `dry_run` | no | `false` | If true, validate inputs and report what would be written without writing anything. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** `confirm=true` required to overwrite an existing file; supports `dry_run`. Filesystem writes are not part of Unity's Undo system.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,140 @@
|
||||
# Baking commands
|
||||
|
||||
Bake and clear precomputed scene data: lightmaps, NavMesh, and occlusion culling. Each `bake_*` runs asynchronously (returns immediately) — poll the matching `*_bake_status` until `completed`. The `clear_*` commands are destructive and require `confirm=true`. The `get_*_settings` / `set_*_settings` pairs read and tune the bake parameters.
|
||||
|
||||
## Lighting
|
||||
|
||||
### `bake_lighting`
|
||||
Trigger an async lightmap bake of the open scene(s) via Lightmapping.BakeAsync(). Returns immediately; poll `lighting_bake_status` until completed.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `confirm` | no | `false` | Recommended (true): a bake overwrites existing lightmap data. Accepted for parity; not required. |
|
||||
| `dry_run` | no | `false` | If true, validate there is an open bakeable scene and return the current lighting settings without baking. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `lighting_bake_status`
|
||||
Get the status of the last lighting bake: idle | baking | completed.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `cancel_lighting_bake`
|
||||
Cancel an in-progress lighting bake (Lightmapping.Cancel()).
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `clear_baked_lighting`
|
||||
Clear baked lightmap data for the open scene(s). Destructive: requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `confirm` | no | `false` | Must be true to actually clear (destructive, not undoable via Unity's Undo). |
|
||||
| `include_disk_cache` | no | `false` | If true, also clear the GI disk cache (Lightmapping.ClearDiskCache()). |
|
||||
| `dry_run` | no | `false` | If true, report what would be cleared without clearing. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `get_lighting_settings`
|
||||
Read the active LightingSettings (lightmapper, bounces, resolution, directional mode, AO, etc.).
|
||||
|
||||
**Returns:** `LightingSettingsResult`
|
||||
|
||||
### `set_lighting_settings`
|
||||
Apply a subset of lighting settings to the active LightingSettings. Returns `{ applied[], unknown[] }`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | yes | `–` | JSON object with a subset of lighting fields to set (same names/enums as get_lighting_settings). |
|
||||
| `dry_run` | no | `false` | If true, validate the keys and report applied/unknown without changing anything. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
## NavMesh
|
||||
|
||||
### `bake_navmesh`
|
||||
Trigger an async legacy NavMesh bake of the open scene(s) via UnityEditor.AI.NavMeshBuilder. Returns immediately; poll `navmesh_bake_status` until completed.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `confirm` | no | `false` | Accepted for parity (a bake overwrites the existing NavMesh); not required. |
|
||||
| `dry_run` | no | `false` | If true, validate there is an open scene and return current NavMesh settings without baking. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `navmesh_bake_status`
|
||||
Get the status of the last NavMesh bake: idle | baking | completed.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `cancel_navmesh_bake`
|
||||
Cancel an in-progress NavMesh bake (NavMeshBuilder.Cancel()).
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `clear_navmesh`
|
||||
Clear the baked NavMesh for the open scene(s). Destructive: requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `confirm` | no | `false` | Must be true to actually clear (destructive, not undoable via Unity's Undo). |
|
||||
| `dry_run` | no | `false` | If true, report what would be cleared without clearing. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `get_navmesh_settings`
|
||||
Read the default agent's legacy NavMesh bake settings (agentRadius/Height/Slope/Climb, minRegionArea, voxelSize).
|
||||
|
||||
**Returns:** `NavMeshSettingsResult`
|
||||
|
||||
### `set_navmesh_settings`
|
||||
Apply a subset of legacy NavMesh bake settings to the default agent. Returns `{ applied[], unknown[] }`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | yes | `–` | JSON object with a subset of NavMesh fields to set (same names as get_navmesh_settings). |
|
||||
| `dry_run` | no | `false` | If true, validate the keys and report applied/unknown without changing anything. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `bake_navmesh_surfaces`
|
||||
Bake NavMeshSurface components (AI Navigation package). v1 stub: returns package_not_found when the package is absent.
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
## Occlusion culling
|
||||
|
||||
### `bake_occlusion_culling`
|
||||
Trigger an async occlusion-culling bake of the open scene(s) via StaticOcclusionCulling.GenerateInBackground(). Returns immediately; poll `occlusion_bake_status` until completed.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `smallest_occluder` | no | `–` | Smallest object that will occlude others (meters). Defaults to Unity's current value. |
|
||||
| `smallest_hole` | no | `–` | Smallest gap geometry can have that the view can see through (meters). Defaults to Unity's current value. |
|
||||
| `backface_threshold` | no | `–` | Backface threshold (1-100); lower trims more backfaces. Defaults to Unity's current value. |
|
||||
| `confirm` | no | `false` | Accepted for parity (a bake overwrites existing occlusion data); not required. |
|
||||
| `dry_run` | no | `false` | If true, validate there is an open scene and report the parameters that would be used without baking. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `occlusion_bake_status`
|
||||
Get the status of the last occlusion bake: idle | baking | completed.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `cancel_occlusion_bake`
|
||||
Cancel an in-progress occlusion bake (StaticOcclusionCulling.Cancel()).
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `clear_occlusion_culling`
|
||||
Clear baked occlusion-culling data for the open scene(s). Destructive: requires confirm=true.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `confirm` | no | `false` | Must be true to actually clear (destructive, not undoable via Unity's Undo). |
|
||||
| `dry_run` | no | `false` | If true, report what would be cleared without clearing. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
# Build, compilation & test commands
|
||||
|
||||
These commands drive the build/compile/test dev loop, plus build configuration: triggering Player builds and reading the resulting BuildReport, switching the active build target, enumerating targets, reading/writing EditorUserBuildSettings, and listing Build Profiles. Several commands are asynchronous: trigger the operation, then poll a matching `*_status` command until it reports completion. The client must tolerate connection errors during a domain reload (recompile, target switch) or a long blocking build.
|
||||
|
||||
### `build`
|
||||
Trigger an async Player build and report the full BuildReport. Returns immediately (queued); poll build_status until status is 'completed'. DetailedBuildReport is included by default unless 'options' is supplied. Use dry_run to validate without building.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | no | `–` | BuildTarget name (e.g. StandaloneWindows64). Defaults to the active target. Must be installed. |
|
||||
| `outputPath` | no | `–` | Output path (absolute, or relative to the project root). Defaults to the last/auto path. |
|
||||
| `profileName` | no | `–` | Build Profile name to activate before building (Unity 6 only; ignored otherwise). |
|
||||
| `options` | no | `–` | BuildOptions names. Omit to get just DetailedBuildReport; supplying any disables that default. |
|
||||
| `scenes` | no | `–` | Scene asset paths to build (e.g. Assets/Scenes/Main.unity). Defaults to EditorBuildSettings. |
|
||||
| `confirm` | no | `false` | Acknowledge and run the build; without it the call is refused. Use `dry_run` to validate only. |
|
||||
| `dry_run` | no | `false` | Validate target/outputPath/scenes without building. |
|
||||
|
||||
Supported `options` values (case-insensitive): `Development`, `AllowDebugging`, `ConnectWithProfiler`, `EnableHeadlessMode`, `SymlinkSources`, `BuildAdditionalStreamedScenes`, `CleanBuildCache`, `DetailedBuildReport`. Any unrecognized value is a validation error.
|
||||
|
||||
**Returns:** `object` (transient payloads: `queued` / `busy` / `dry_run` / `error`; the finished report is read via `build_status`).
|
||||
**Notes:** `MainThreadRequired = false`. Async — validates + queues, returns `queued` immediately, then an editor tick runs the (blocking) build; poll `build_status` until status is `completed`. Only one build at a time (returns `busy` otherwise). Mutating: gated by the `confirm`/`dry_run` convention — pass `confirm=true` for a real build, or `dry_run=true` to validate target/outputPath/scenes without building (nothing is queued on a dry run or on validation failure).
|
||||
|
||||
### `build_status`
|
||||
Status of the current/most recent build: idle | queued | building | completed, with the full BuildReport (files, packedAssets, buildSteps, errors, warnings) once completed. Retained until the next build.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string` (JSON). `idle` when no build has run; `queued`/`building` (the latter with live `elapsedMs`) while in progress; a full `BuildReportResult` once `completed`.
|
||||
|
||||
`BuildReportResult` fields (returned when `status` is `completed`):
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `status` | Always `completed` here. |
|
||||
| `buildId` | Id returned by the triggering `build` call. |
|
||||
| `result` | `Succeeded` \| `Failed` \| `Cancelled` \| `Unknown`. |
|
||||
| `platform` | Build target the report is for. |
|
||||
| `outputPath` | Final output location. |
|
||||
| `totalSizeBytes` | Total build size in bytes. |
|
||||
| `buildTimeMs` | Total build duration in milliseconds. |
|
||||
| `buildStartedAt` / `buildEndedAt` | ISO-8601 timestamps (omitted when unset). |
|
||||
| `totalWarnings` / `totalErrors` | Aggregate counts from the report summary. |
|
||||
| `files` | Output files (path, role, sizeBytes). Present only on success. |
|
||||
| `packedAssets` | Packed bundles with per-asset breakdown. Present only on success and requires DetailedBuildReport. |
|
||||
| `buildSteps` | Per-step name, durationMs, depth, and messages. |
|
||||
| `errors` / `warnings` | Build issues, each with `message` and best-effort `file`. |
|
||||
|
||||
**Notes:** `MainThreadRequired = false`. Reads a Temp status file off-thread, so polling keeps working while a build holds the main thread. The file also survives the domain reload a build can incur, so the last report is retained until the next build.
|
||||
|
||||
### `switch_build_target`
|
||||
Switch the active build target (destructive, long-running: triggers a full reimport + domain reload). Requires confirm=true. Returns immediately; poll switch_build_target_status.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | `–` | BuildTarget name to switch to (must be installed; see list_build_targets). |
|
||||
| `confirm` | no | `false` | Apply the switch. Without it the call is refused. |
|
||||
|
||||
**Returns:** `object` (`switching` / `busy` / `completed` / `error`). Returns `completed` immediately if already on the requested target.
|
||||
**Notes:** `MainThreadRequired = false`. Async — validates + queues, returns `switching` immediately, then an editor tick performs the (blocking) switch; poll `switch_build_target_status` until `completed`. Only one switch at a time (returns `busy` otherwise). Mutating and confirm-gated: without `confirm=true` the call is refused. The status file survives the domain reload the switch causes, and is reconciled against the active target on the next load.
|
||||
|
||||
### `switch_build_target_status`
|
||||
Status of the last target switch: idle | switching | completed (with success + activeBuildTarget).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string` (JSON). `idle`, `switching`, or `completed` (with `success` and `activeBuildTarget`, or `errors` on failure).
|
||||
**Notes:** `MainThreadRequired = false`. Reads a Temp status file off-thread, so it keeps answering while the switch holds the main thread.
|
||||
|
||||
### `list_build_targets`
|
||||
List the known BuildTarget values with their group and whether build support is installed.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object` (list of `BuildTargetInfo`: `name`, `displayName`, `targetGroup`, `isInstalled`), sorted by group then name. Obsolete and sentinel targets are excluded.
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `get_build_settings`
|
||||
Read the current build configuration from EditorUserBuildSettings / EditorBuildSettings.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object` (`BuildSettingsResult`).
|
||||
|
||||
`BuildSettingsResult` fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `activeBuildTarget` | Active BuildTarget name. |
|
||||
| `activeBuildTargetGroup` | Active BuildTargetGroup name. |
|
||||
| `developmentBuild` | Whether a Development Player is configured. |
|
||||
| `allowDebugging` | Whether script debugging is allowed. |
|
||||
| `connectWithProfiler` | Whether the Profiler auto-connects. |
|
||||
| `buildScriptsOnly` | Whether only scripts are built (skip data). |
|
||||
| `symlinkSources` | Whether runtime/plugin sources are symlinked. |
|
||||
| `il2CppCodeGeneration` | `OptimizeSpeed` \| `OptimizeSize` for the active target. |
|
||||
| `scenes` | Build Settings scene list (each: `path`, `guid`, `enabled`). |
|
||||
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_build_settings`
|
||||
Set mutable EditorUserBuildSettings fields. Does NOT manage scenes (use add_scene_to_build / remove_scene_from_build) or switch target (use switch_build_target). Use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged. |
|
||||
| `confirm` | no | `false` | Apply the changes. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields (a structured input DTO; every field is optional — only supplied fields change):
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `developmentBuild` | Build a Development Player (enables the debugger/profiler). |
|
||||
| `allowDebugging` | Allow script debugging (only effective with developmentBuild=true). |
|
||||
| `connectWithProfiler` | Auto-connect the Profiler (only effective with developmentBuild=true). |
|
||||
| `buildScriptsOnly` | Build only the scripts (skip data) for faster iteration. |
|
||||
| `symlinkSources` | Symlink runtime/plugin sources instead of copying (where supported). |
|
||||
| `il2CppCodeGeneration` | IL2CPP code generation for the active target: OptimizeSpeed \| OptimizeSize. |
|
||||
|
||||
**Returns:** `object` (`SetBuildSettingsResult`: `success`, `dryRun`, `applied` map of fields that changed, `skipped` map of supplied fields that already matched, `message`).
|
||||
**Notes:** `MainThreadRequired = true`. Mutating: refused unless `confirm=true` (or `dry_run=true` to preview). Fields already at the requested value are reported under `skipped` rather than re-applied. Fails if no `settings` object is provided.
|
||||
|
||||
### `list_build_profiles`
|
||||
List Build Profile assets in the project (Unity 6 only). Returns feature_unavailable on earlier versions.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object` (list of `BuildProfileInfo`: `name`, `guid`, `platform`, `isActive`), or `{ error, code = "feature_unavailable" }` on editors older than Unity 6.
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `recompile`
|
||||
Force a script recompile (works while unfocused/minimized). Poll recompile_status for completion.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = true`. Async — poll `recompile_status` until status is `completed` or `up_to_date`. A successful compile triggers a domain reload, so the triggering request cannot stay open.
|
||||
|
||||
### `recompile_status`
|
||||
Get the status of the last recompile: idle | triggered | compiling | completed | up_to_date.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = false`.
|
||||
|
||||
### `list_tests`
|
||||
List all available tests (EditMode and/or PlayMode) without running them.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `mode` | no | `all` | Test mode: all, editor, playmode (default: all) |
|
||||
|
||||
**Returns:** `TestListResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `run_tests`
|
||||
Execute Unity tests with filtering options.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `mode` | no | `all` | Test mode: all, editor, playmode (default: all) |
|
||||
| `filter` | no | `–` | Test name filter pattern (case-insensitive partial match) |
|
||||
| `filter_type` | no | `testName` | Filter type: testName, assembly, category (default: testName) |
|
||||
| `include_explicit` | no | `false` | Include tests marked with [Explicit] attribute |
|
||||
| `async_tests` | no | `false` | Run asynchronously - return immediately, poll /test-status for results |
|
||||
| `timeout` | no | `300` | Test execution timeout in seconds (default: 300) |
|
||||
|
||||
**Returns:** `TestExecutionResponse`
|
||||
**Notes:** `MainThreadRequired = true`. Synchronous by default; with `async_tests=true` it returns immediately — poll `test_status` for results.
|
||||
|
||||
### `test_status`
|
||||
Get status of running async test execution.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = false`.
|
||||
|
||||
### `cancel_tests`
|
||||
Cancel running test execution.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,58 @@
|
||||
# Capture commands
|
||||
|
||||
Commands that render a camera, the Scene View, or a UI Toolkit element to a PNG and return it base64-encoded so an agent can "see" the editor (or a running player) without a display.
|
||||
|
||||
### `capture_game_view`
|
||||
Render a camera to a PNG. Returns it inline as base64, unless `save_path` is set — then the result is **path-only** (no base64) so agent tool results stay small; pass `include_inline_image=true` to get both.
|
||||
|
||||
Parameter interactions: `include_inline_image` is only meaningful together with `save_path` (without one, the inline image is always returned). `max_resolution` only applies when an inline image is actually returned — i.e. no `save_path`, or `save_path` + `include_inline_image=true`; it has **no effect** when `save_path` is set without `include_inline_image=true`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `width` | no | `1280` | Output width in px (default 1280; capped 4096). |
|
||||
| `height` | no | `720` | Output height in px (default 720; capped 4096). |
|
||||
| `camera` | no | `–` | Optional camera name; defaults to Camera.main, else the first enabled camera. |
|
||||
| `save_path` | no | `–` | Optional project-relative path to write the PNG (e.g. Screenshots/foo.png). When set, the result omits the inline base64 image unless `include_inline_image=true`. |
|
||||
| `include_inline_image` | no | `false` | Also return the image inline as base64 when `save_path` is set. |
|
||||
| `max_resolution` | no | `0` | Cap on the inline image's longest edge (e.g. 512), preserving aspect ratio. No effect when `save_path` is set without `include_inline_image=true`. The `save_path` file keeps the requested resolution; a downscaled inline copy is reported via `inlineWidth`/`inlineHeight`. |
|
||||
|
||||
**Returns:** `CaptureResult`
|
||||
|
||||
### `capture_scene_view`
|
||||
Render the active Scene View to a PNG. Same result contract and parameter interactions as `capture_game_view`: inline base64, or path-only when `save_path` is set (opt back in with `include_inline_image=true`; `max_resolution` has no effect when `save_path` is set without it).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `width` | no | `1280` | Output width in px (default 1280; capped 4096). |
|
||||
| `height` | no | `720` | Output height in px (default 720; capped 4096). |
|
||||
| `save_path` | no | `–` | Optional project-relative path to write the PNG (e.g. Screenshots/foo.png). When set, the result omits the inline base64 image unless `include_inline_image=true`. |
|
||||
| `include_inline_image` | no | `false` | Also return the image inline as base64 when `save_path` is set. |
|
||||
| `max_resolution` | no | `0` | Cap on the inline image's longest edge (e.g. 512), preserving aspect ratio. No effect when `save_path` is set without `include_inline_image=true`. The `save_path` file keeps the requested resolution; a downscaled inline copy is reported via `inlineWidth`/`inlineHeight`. |
|
||||
|
||||
**Returns:** `CaptureResult`
|
||||
|
||||
### `capture_editor_element`
|
||||
Capture a UI Toolkit VisualElement (by selector) from an EditorWindow to a PNG; returns path + base64.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `window` | yes | `–` | EditorWindow type name (e.g. InspectorWindow) or window title to capture from. |
|
||||
| `selector` | yes | `–` | Element selector: '#name', '.class', a type name (e.g. Button), descendant (space) / child ('>') chains, optional pseudo-states (:checked,:hover,:focus,:active,:enabled,:disabled,:not(...)). |
|
||||
| `output` | no | `–` | Output PNG path (absolute, or relative to the project root). Defaults to a timestamped file under <project>/Temp/pipeline-screenshots/. |
|
||||
|
||||
**Returns:** `CaptureElementResponse`
|
||||
**Notes:** `MainThreadRequired = true`. Unity 6000.7+ only.
|
||||
|
||||
### `capture_runtime_element`
|
||||
Capture a UI Toolkit VisualElement (by selector) from a live runtime panel (UIDocument or PanelRenderer) to a PNG; returns path + base64.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `panel` | no | `–` | Name of the target panel: matches the PanelSettings asset name or the host GameObject name (UIDocument or PanelRenderer). Optional when exactly one panel exists. |
|
||||
| `selector` | yes | `–` | Element selector: '#name', '.class', a type name (e.g. Button), descendant (space) / child ('>') chains, optional pseudo-states (:checked,:hover,:focus,:active,:enabled,:disabled,:not(...)). |
|
||||
| `output` | no | `–` | Output PNG path (absolute, or relative to Application.persistentDataPath). Defaults to a timestamped file under Application.persistentDataPath. |
|
||||
|
||||
**Returns:** `CaptureElementResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`. Unity 6000.7+ only.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
# Editor lifecycle & observability commands
|
||||
|
||||
Commands to control Editor play mode, focus, and menus, and to observe the Editor's state, console, and performance.
|
||||
|
||||
### `editor_play`
|
||||
Enter Unity Editor play mode.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `editor_stop`
|
||||
Exit Unity Editor play mode.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `editor_pause`
|
||||
Pause Unity Editor play mode.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
|
||||
### `editor_status`
|
||||
Get detailed Unity Editor status and state information.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `StatusResponse`
|
||||
|
||||
### `editor_focus`
|
||||
Bring the Unity Editor window to the foreground.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `menu`
|
||||
Execute an Editor menu item by path, or list available items when no path is given.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | no | `–` | Menu item path to execute, e.g. "Assets/Reimport All". Omit to list available menu items. |
|
||||
|
||||
**Returns:** `MenuResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `screenshot`
|
||||
Capture the Scene or Game view as a PNG and return its file path.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `view` | no | `game` | Which view to capture: 'game' (default) or 'scene' |
|
||||
| `output` | no | `–` | Output PNG path (absolute, or relative to the project root). Defaults to a timestamped file under <project>/Temp/pipeline-screenshots/. |
|
||||
| `width` | no | `0` | Output width in pixels. 0 (default) uses the view camera's current width. |
|
||||
| `height` | no | `0` | Output height in pixels. 0 (default) uses the view camera's current height. |
|
||||
|
||||
**Returns:** `ScreenshotResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_autotick`
|
||||
Keep the editor ticking while unfocused by forcing EditorApplication.SignalTick at a throttled rate.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `enable` | no | `true` | Enable (true) or disable (false) auto-tick mode |
|
||||
| `interval_ms` | no | `16` | Minimum milliseconds between forced ticks. 0 = every update (max rate, pegs a CPU core). Default 16 (~60Hz). |
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`. State is static and resets on domain reload (turns itself off after a recompile).
|
||||
|
||||
### `get_console_logs`
|
||||
Read recently captured Editor console logs (structured).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `severity` | no | `all` | Filter: all | log | warning | error. 'all' = every entry; 'log' = Log only; 'warning' = Warning only; 'error' = Error/Exception/Assert only. |
|
||||
| `limit` | no | `100` | Max entries to return (most-recent first), capped at 1000. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `clear_console`
|
||||
Clear the captured log buffer and the Unity Editor console.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `get_performance_stats`
|
||||
Read render, memory, and frame-timing stats (structured, read-only).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `PerformanceStats`
|
||||
|
||||
### `get_authoring_root`
|
||||
Get the base folder (under Assets/) that bare authoring paths resolve against.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `set_authoring_root`
|
||||
Set the base folder (under Assets/) that bare authoring paths resolve against and are confined to. Use 'Assets' for full project access.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `root` | yes | `–` | Project-relative folder under Assets/, e.g. Assets/AgentWork. Use 'Assets' to allow the whole project. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
# GameObject & component commands
|
||||
|
||||
Commands for creating GameObjects, querying the scene hierarchy, mutating the core GameObject/Transform surface, and adding/removing components and editing their serialized properties. Scene mutations are wrapped in Unity's Undo system (so a multi-step action reverts as one collapsible step) and are blocked during Play mode. Objects are referenced by an `ObjectRef` handle (globalId/path/guid/instanceId/hierarchyPath), and results come back as `AuthoringResult` identities you can chain into a follow-up call.
|
||||
|
||||
### `create_gameobject`
|
||||
Create an empty GameObject or a built-in primitive (cube/sphere/capsule/cylinder/plane/quad) in the active scene.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `name` | no | `–` | Name for the new GameObject. Defaults to 'GameObject' (or the primitive name). |
|
||||
| `primitive` | no | `–` | Optional primitive type: cube, sphere, capsule, cylinder, plane, quad. Omit for an empty GameObject. |
|
||||
| `parent` | no | `–` | Optional parent handle (globalId/path/guid/instanceId/hierarchyPath). The new object becomes a child of it. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `create_gameobjects`
|
||||
Batch-create N empty GameObjects or primitives in one call. Optional positions/rotations/scales are arrays of [x,y,z] (length must equal count). Returns the created identities.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `name` | no | `–` | Base name. With count>1 and no explicit names, objects are suffixed Name1..NameN. |
|
||||
| `primitive` | no | `–` | Optional primitive type: cube, sphere, capsule, cylinder, plane, quad. Omit for empty GameObjects. |
|
||||
| `parent` | no | `–` | Optional parent handle. Every created object becomes a child of it. |
|
||||
| `count` | no | `1` | How many GameObjects to create. Default 1. |
|
||||
| `positions` | no | `–` | Local positions, one [x,y,z] per object. Length must equal count when supplied. |
|
||||
| `rotations` | no | `–` | Local Euler rotations (degrees), one [x,y,z] per object. Length must equal count when supplied. |
|
||||
| `scales` | no | `–` | Local scales, one [x,y,z] per object. Length must equal count when supplied. |
|
||||
|
||||
**Returns:** `CreateGameObjectsResult`
|
||||
**Notes:** Undo-able (the whole batch reverts as one step); blocked during Play mode.
|
||||
|
||||
### `find_gameobjects`
|
||||
Find GameObjects in loaded scenes by name, tag, component type, and/or hierarchy path (filters are combined). Returns structured identities.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `name` | no | `–` | Exact name to match. |
|
||||
| `tag` | no | `–` | Tag to match (e.g. 'Player'). |
|
||||
| `type` | no | `–` | Component type name to match (e.g. 'Rigidbody', 'UnityEngine.Camera'). |
|
||||
| `hierarchy_path` | no | `–` | Exact hierarchy path to match (e.g. '/Root/Child'). |
|
||||
| `include_inactive` | no | `true` | Include inactive GameObjects. Default true. |
|
||||
|
||||
**Returns:** `FindGameObjectsResult`
|
||||
|
||||
### `set_transform`
|
||||
Set a GameObject's local position/rotation(euler)/scale. Omitted channels are left unchanged.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject to modify. |
|
||||
| `position` | no | `–` | Local position as [x,y,z]. |
|
||||
| `rotation` | no | `–` | Local rotation as Euler angles [x,y,z] in degrees. |
|
||||
| `scale` | no | `–` | Local scale as [x,y,z]. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `set_parent`
|
||||
Reparent a GameObject under a new parent, or detach it to scene root when no parent is given.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject to reparent. |
|
||||
| `parent` | no | `–` | Handle of the new parent. Omit (or empty) to move the object to the scene root. |
|
||||
| `world_position_stays` | no | `true` | Keep the object's world position when reparenting. Default true. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `set_active`
|
||||
Set a GameObject's active self-state (activeSelf).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject. |
|
||||
| `active` | yes | – | Desired active state. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `set_tag`
|
||||
Set a GameObject's tag (the tag must already exist in the project).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject. |
|
||||
| `tag` | yes | – | Tag to assign (must exist in the Tag Manager). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `set_layer`
|
||||
Set a GameObject's layer by name or numeric index (0-31).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject. |
|
||||
| `layer` | yes | – | Layer name (e.g. 'UI') or numeric index 0-31. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `rename_gameobject`
|
||||
Rename a GameObject.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject. |
|
||||
| `name` | yes | – | New name. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `delete_gameobject`
|
||||
Delete a GameObject from the scene (reversible via Undo).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject to delete. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode. The result describes the object's identity captured before destruction.
|
||||
|
||||
### `add_component`
|
||||
Add a component (by type name) to a GameObject.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the GameObject. |
|
||||
| `type` | yes | – | Component type name (e.g. 'Rigidbody' or 'UnityEngine.Camera'). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `remove_component`
|
||||
Remove a component from a GameObject. Provide either a component handle (target) or a GameObject handle (target) plus a type name.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the component to remove, OR of the GameObject when 'type' is given. |
|
||||
| `type` | no | `–` | Component type name to remove from the target GameObject (omit when 'target' already points at a component). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able; blocked during Play mode.
|
||||
|
||||
### `get_component_properties`
|
||||
Get a component's serialized properties as a JSON map. Address the component by handle, or by GameObject handle + type.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the component, OR of the GameObject when 'type' is given. |
|
||||
| `type` | no | `–` | Component type name on the target GameObject (omit when 'target' is a component handle). |
|
||||
|
||||
**Returns:** `ComponentPropertiesResult`
|
||||
|
||||
### `set_component_properties`
|
||||
Set serialized properties on a component (one Undo step). 'properties' maps property name -> value; object references accept an ObjectRef handle.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Handle of the component, OR of the GameObject when 'type' is given. |
|
||||
| `properties` | yes | – | Map of serialized property name to value. Vectors/colors are arrays; object refs are handle objects. |
|
||||
| `type` | no | `–` | Component type name on the target GameObject (omit when 'target' is a component handle). |
|
||||
|
||||
**Returns:** `ComponentPropertiesResult`
|
||||
**Notes:** Undo-able (one Undo step); blocked during Play mode. An unknown property name fails the whole batch (no partial apply).
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# Material & shader commands
|
||||
|
||||
Read and edit material shader properties, and discover/introspect shaders so an agent can pick a valid shader name and property set.
|
||||
|
||||
## Materials
|
||||
|
||||
### `get_material_properties`
|
||||
Read a material's shader, render queue, enabled keywords, and all shader properties with their current values (Color as [r,g,b,a], Vector as [x,y,z,w], Texture as an object reference).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `material` | yes | `–` | Reference to the .mat asset (or a loaded material) to read (path / guid / globalId / instanceId). |
|
||||
|
||||
**Returns:** `MaterialPropertiesResult`
|
||||
|
||||
### `set_material_properties`
|
||||
Set shader properties on a material (Float/Range/Int=number; Color=[r,g,b,a] or "#RRGGBBAA" hex; Vector=[x,y,z,w]; Texture=an object reference or null to clear), optionally reassign the shader, set the render queue, and toggle keywords. Unknown names / type mismatches are reported in `unknown[]`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `material` | yes | `–` | Reference to the .mat asset (or a loaded material) to edit (path / guid / globalId / instanceId). |
|
||||
| `shader` | no | `–` | Reassign the material's shader by name (e.g. "Standard", "Universal Render Pipeline/Lit", or a Shader Graph shader name). Applied before properties so new property names resolve against the new shader. |
|
||||
| `properties` | no | `–` | JSON object of shader property name -> value. Names must include the leading underscore (e.g. _BaseColor). Float/Range/Int=number; Color=[r,g,b,a] or hex string; Vector=[x,y,z,w]; Texture=an object reference {guid/path} or null. |
|
||||
| `renderQueue` | no | `–` | Explicit render queue, or -1 to inherit from the shader. Omit to leave unchanged. |
|
||||
| `enableKeywords` | no | `–` | Shader keywords to enable (e.g. _NORMALMAP, _EMISSION). |
|
||||
| `disableKeywords` | no | `–` | Shader keywords to disable. |
|
||||
| `confirm` | no | `false` | Reserved for parity; editing an existing material is non-destructive and undoable, so it is not required. |
|
||||
| `dry_run` | no | `false` | If true, validate the shader, resolve property names and texture refs, and report applied[]/unknown[] without writing anything. |
|
||||
|
||||
**Returns:** `SetMaterialPropertiesResult`
|
||||
|
||||
## Shaders
|
||||
|
||||
### `list_shaders`
|
||||
Discover available shaders so an agent can pick a valid name for set_material_properties / create_asset. Returns `[{ name, assetPath|null, isBuiltin, isSupported }]`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `filter` | no | `–` | Case-insensitive substring matched against the shader name (e.g. "URP", "Lit"). |
|
||||
| `includeBuiltin` | no | `true` | Include built-in/engine shaders (those with no project asset path). |
|
||||
| `limit` | no | `200` | Maximum number of shaders to return. |
|
||||
|
||||
**Returns:** `object` (list of `ShaderInfo`)
|
||||
|
||||
### `get_shader_properties`
|
||||
Introspect a shader's declared property list (name, description, type Color|Vector|Float|Range|TexEnv|Int, range, textureDimension, flags). Provide `shader` (by name) OR `material` (read the shader off that material).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `shader` | no | `–` | Shader name (e.g. "Universal Render Pipeline/Lit"). Provide this OR 'material'. |
|
||||
| `material` | no | `–` | Reference to a material to read the shader from instead of naming it. Provide this OR 'shader'. |
|
||||
|
||||
**Returns:** `ShaderPropertiesResult`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Navigation & selection commands
|
||||
|
||||
Commands to read and drive the Editor selection, and to run Unity Search queries. All commands are read-only or non-destructive and run on the main thread.
|
||||
|
||||
### `get_selection`
|
||||
Read the current Editor selection as structured object identities.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `SelectionResult`
|
||||
|
||||
### `set_selection`
|
||||
Set the Editor selection to the given assets/scene objects.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `instance_ids` | no | `–` | Scene/loaded object instance IDs to select. |
|
||||
| `paths` | no | `–` | Asset paths to select (e.g. Assets/Foo.prefab). |
|
||||
|
||||
**Returns:** `SelectionResult`
|
||||
|
||||
### `search`
|
||||
Run a Unity Search query and return structured results.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `query` | yes | `–` | Unity Search query string, e.g. 't:Material', 'p: my asset', 'h: Main Camera'. |
|
||||
| `limit` | no | `50` | Max results to return (capped 200). |
|
||||
|
||||
**Returns:** `SearchResult`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
# Package Manager commands
|
||||
|
||||
These commands query and modify the project's UPM package set (list, search, add, remove, resolve, status) over `UnityEditor.PackageManager`. Read-only queries block until the registry responds and return synchronously; mutating commands (`package_add`/`package_remove`) require `confirm=true`, support `dry_run` previews, and are async by default (poll `package_status`) with an optional `wait=true` to block until done.
|
||||
|
||||
### `package_list`
|
||||
List packages by scope: installed (default) | available (registry) | all (both). Returns the full result synchronously — available/all block until the registry query completes.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `scope` | no | `installed` | Which packages to list: installed (default) | available | all. |
|
||||
| `include_indirect` | no | `true` | Include indirect (transitive) installed dependencies (applies to scope=installed/all). |
|
||||
| `offline` | no | `false` | For available/all: query the local cache instead of the registry. |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = false`. Synchronous — `available`/`all` start a registry query and block until it completes (up to a 25s timeout); `installed` reads the resolved set inline on the main thread.
|
||||
|
||||
### `package_search`
|
||||
Search packages available in the registry. Provide a name (e.g. com.unity.foo) or omit to list all. Returns the full result synchronously (blocks until the registry query completes).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `query` | no | `–` | Package name to search for. Omit/empty to list all available packages. |
|
||||
| `offline` | no | `false` | Search the local cache only. |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = false`. Synchronous — blocks until the registry query completes (up to a 25s timeout). Each result is flagged with whether it is currently installed.
|
||||
|
||||
### `package_add`
|
||||
Add a UPM package by name@version, git URL, or 'file:' local path. Async by default (returns in_progress; poll package_status); pass wait=true to block until added. A recompile/domain reload follows — poll recompile_status. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `identifier` | yes | `–` | Package to add: 'com.unity.foo@1.2.3', a git URL, or 'file:../Path'. |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
| `wait` | no | `false` | Block until the operation completes and return the result (synchronous). Default: return immediately and poll package_status. |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = false`. Mutating — requires `confirm=true`; `dry_run=true` returns a preview without applying. Async by default (returns `in_progress`; poll `package_status`); with `wait=true` it blocks until completion (up to a 25s timeout). A successful add triggers a recompile/domain reload — poll `recompile_status`. Returns `busy` if another package operation is already in progress.
|
||||
|
||||
### `package_remove`
|
||||
Remove a UPM package by name. Async by default (returns in_progress; poll package_status); pass wait=true to block until removed. A recompile/domain reload follows — poll recompile_status. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `name` | yes | `–` | Package name to remove (e.g. com.unity.foo). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
| `wait` | no | `false` | Block until the operation completes and return the result (synchronous). Default: return immediately and poll package_status. |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = false`. Mutating — requires `confirm=true`; `dry_run=true` returns a preview without applying. Async by default (returns `in_progress`; poll `package_status`); with `wait=true` it blocks until completion (up to a 25s timeout). A successful remove triggers a recompile/domain reload — poll `recompile_status`; the reload can drop a synchronous reply, so `package_status` confirms the outcome. Returns `busy` if another package operation is already in progress.
|
||||
|
||||
### `package_resolve`
|
||||
Resolve/refresh packages from the manifest (re-fetch and re-link). May trigger a recompile/domain reload — poll recompile_status. Its outcome is recorded for package_status.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** `MainThreadRequired = true`. Fire-and-forget — `Client.Resolve()` schedules a resolve on a later tick, so the response returns before any reload. May trigger a recompile/domain reload — poll `recompile_status`. Its outcome is recorded in the status file, so `package_status` validates it.
|
||||
|
||||
### `package_status`
|
||||
Status of the last async package operation (add/remove/resolve): idle | in_progress | completed | failed, with the added package, manifest, and any error.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = false`. Reads a Temp status file that survives the domain reload an add/remove/resolve triggers, so a lost synchronous reply or an interrupted async op is recoverable by polling. Returns `{"status":"idle"}` when no operation has run.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,84 @@
|
||||
# Prefab commands
|
||||
|
||||
Commands covering the prefab lifecycle an agent needs to build content procedurally: saving a configured GameObject as a prefab asset, instantiating it into a scene, deriving a variant, applying/reverting instance overrides, unpacking, and editing prefab contents through the prefab stage. Asset paths are sandboxed to the authoring root; scene-side mutations are Undo-able, but prefab asset writes are AssetDatabase operations and are not part of Unity's Undo system.
|
||||
|
||||
### `create_prefab`
|
||||
Save a GameObject as a prefab asset at a project path; the source becomes a connected instance.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `source` | yes | – | Reference to the source GameObject to save as a prefab (globalId/path/guid/instanceId/hierarchyPath). |
|
||||
| `path` | yes | – | Prefab asset path relative to the authoring root (the Assets/ prefix is optional and the .prefab extension is added if missing). e.g. Prefabs/Enemy or Prefabs/Enemy.prefab |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Scene-side effects are Undo-able; the prefab asset write is not undoable.
|
||||
|
||||
### `instantiate_prefab`
|
||||
Instantiate a prefab asset into a loaded scene and return the created instance.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `prefab` | yes | – | Reference to the prefab asset to instantiate (path/guid/globalId). |
|
||||
| `scene_path` | no | `–` | Optional path of a loaded scene to instantiate into; defaults to the active scene. |
|
||||
| `name` | no | `–` | Optional name for the created instance; defaults to the prefab name. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able.
|
||||
|
||||
### `create_prefab_variant`
|
||||
Create a prefab variant asset that inherits from a base prefab.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `base` | yes | – | Reference to the base prefab asset (path/guid/globalId). |
|
||||
| `path` | yes | – | Variant prefab asset path relative to the authoring root (.prefab added if missing). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Prefab asset write is not undoable.
|
||||
|
||||
### `apply_prefab_overrides`
|
||||
Apply a prefab instance's overrides back to its source prefab asset.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `instance` | yes | – | Reference to a prefab instance GameObject in a scene (instanceId/hierarchyPath/globalId). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Scene-side effects are Undo-able; the asset write is not. The instance's source prefab asset must live under the authoring root.
|
||||
|
||||
### `revert_prefab_overrides`
|
||||
Revert a prefab instance's overrides so it matches its source prefab asset.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `instance` | yes | – | Reference to a prefab instance GameObject in a scene (instanceId/hierarchyPath/globalId). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able.
|
||||
|
||||
### `unpack_prefab`
|
||||
Unpack a prefab instance into plain GameObjects (outermost level or completely).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `instance` | yes | – | Reference to a prefab instance GameObject in a scene (instanceId/hierarchyPath/globalId). |
|
||||
| `completely` | no | `false` | If true, unpack all nested prefab levels (Completely); if false, only the outermost level (OutermostRoot). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able.
|
||||
|
||||
### `save_prefab_contents`
|
||||
Open a prefab asset in an isolated prefab stage, apply a declarative edit, and save it back (nested-prefab safe).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `prefab` | yes | – | Reference to the prefab asset to edit (path/guid/globalId). |
|
||||
| `rename_child` | no | `–` | Optional child name (relative path under the root, e.g. 'Body/Head') to rename. |
|
||||
| `new_name` | no | `–` | New name for the child identified by rename_child. |
|
||||
| `set_active_child` | no | `–` | Optional child name (relative path under the root) whose active state to set. |
|
||||
| `active` | no | `true` | Active state to apply when set_active_child is provided. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Prefab asset write (prefab-stage save) is not part of Unity's Undo system. The prefab asset must live under the authoring root.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
# Project settings commands
|
||||
|
||||
Read and change a representative slice of Unity's project-wide settings (Audio, Graphics, Input, Physics, Player, Quality, Tags & Layers, Time). `get_*` commands read a group's current values into a `ProjectSettingsResponse`; `set_*` commands mutate them through the shared `confirm`/`dry_run` convention, so `confirm=true` is required to apply and `dry_run=true` previews the change without applying it. Every command in this group is `MainThreadRequired = true`. On a `set_*`, omitted fields are left unchanged, and the group is re-read after the write so the response reflects the resulting state. Settings writes are not undoable via Ctrl+Z.
|
||||
|
||||
### `get_audio_settings`
|
||||
Read project Audio settings (volume, rolloff scale, doppler factor).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_audio_settings`
|
||||
Change project Audio settings. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `volume` | no | `–` | Global audio volume (0..1). |
|
||||
| `rolloffScale` | no | `–` | Global rolloff scale. |
|
||||
| `dopplerFactor` | no | `–` | Global doppler factor. |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
### `get_graphics_settings`
|
||||
Read GraphicsSettings (default render pipeline).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_graphics_settings`
|
||||
Set the default render pipeline asset. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `renderPipelineAsset` | no | `–` | Reference (path / guid / globalId) to a RenderPipelineAsset to set as the default. Pass an empty reference (`{}`) to select the built-in pipeline; omit to leave unchanged. |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
### `get_input_settings`
|
||||
Read the legacy Input Manager axes (names and count).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_input_settings`
|
||||
Tune a legacy Input Manager axis (sensitivity/gravity/dead) by name. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Axis change. 'axis' selects the axis by name; omitted numeric fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `axis` | yes | – | Name of the axis to modify (e.g. 'Horizontal'). |
|
||||
| `sensitivity` | no | `–` | New sensitivity. |
|
||||
| `gravity` | no | `–` | New gravity. |
|
||||
| `dead` | no | `–` | New dead-zone size. |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
### `get_physics_settings`
|
||||
Read Physics settings (gravity, solver iterations, bounce threshold).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_physics_settings`
|
||||
Change Physics settings. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `gravityX` | no | `–` | Gravity X component. |
|
||||
| `gravityY` | no | `–` | Gravity Y component (e.g. -9.81). |
|
||||
| `gravityZ` | no | `–` | Gravity Z component. |
|
||||
| `defaultSolverIterations` | no | `–` | Default solver iteration count. |
|
||||
| `bounceThreshold` | no | `–` | Bounce threshold velocity. |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
### `get_player_settings`
|
||||
Read PlayerSettings (company/product/version, scripting backend, API level).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_player_settings`
|
||||
Change PlayerSettings. Requires confirm=true; use dry_run to preview. Scripting backend / API level changes trigger a domain reload.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `companyName` | no | `–` | Company name. |
|
||||
| `productName` | no | `–` | Product name. |
|
||||
| `bundleVersion` | no | `–` | Bundle/application version string. |
|
||||
| `scriptingBackend` | no | `–` | Scripting backend (e.g. Mono2x, IL2CPP). Triggers a domain reload. |
|
||||
| `apiCompatibilityLevel` | no | `–` | API compatibility level (e.g. NET_Standard_2_0, NET_Unity_4_8). Triggers a domain reload. |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`. Changing `scriptingBackend` or `apiCompatibilityLevel` triggers a domain reload (`requiresDomainReload`); scripting-backend / API-level changes are read and written against the active build target.
|
||||
|
||||
### `get_quality_settings`
|
||||
Read QualitySettings (current level, level names, vSync, anti-aliasing).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_quality_settings`
|
||||
Change QualitySettings. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `level` | no | `–` | Quality level index (see levelNames from get_quality_settings). |
|
||||
| `vSyncCount` | no | `–` | VSync count (0 = off, 1, 2). |
|
||||
| `antiAliasing` | no | `–` | MSAA sample count (0, 2, 4, 8). |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
### `get_tags_layers`
|
||||
Read the project's tags and (named) layers.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_tags_layers`
|
||||
Add/remove tags and assign user layer names (index 8-31). Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Tag/layer changes to make (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `addTags` | no | `–` | Tag names to add. |
|
||||
| `removeTags` | no | `–` | Tag names to remove. |
|
||||
| `setLayers` | no | `–` | User layer assignments (index 8-31); array of layer-assignment objects (fields below). |
|
||||
|
||||
`setLayers[]` (layer-assignment) fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `index` | yes | – | Layer index (8-31 for user layers). |
|
||||
| `name` | yes | – | Layer name (empty string clears the slot). |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`. User layers are indices 8-31 (0-7 are reserved).
|
||||
|
||||
### `get_time_settings`
|
||||
Read Time settings (fixedDeltaTime, maximumDeltaTime, timeScale).
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`.
|
||||
|
||||
### `set_time_settings`
|
||||
Change Time settings. Requires confirm=true; use dry_run to preview.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `settings` | no | `–` | Fields to change; omitted fields are left unchanged (fields below). |
|
||||
| `confirm` | no | `false` | Apply the change. Without it the call is refused. |
|
||||
| `dry_run` | no | `false` | Preview the change without applying it. |
|
||||
|
||||
`settings` fields:
|
||||
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `fixedDeltaTime` | no | `–` | Fixed timestep in seconds (e.g. 0.02). |
|
||||
| `maximumDeltaTime` | no | `–` | Maximum allowed timestep in seconds. |
|
||||
| `timeScale` | no | `–` | Time scale (1 = real-time). |
|
||||
|
||||
**Returns:** `ProjectSettingsResponse`
|
||||
**Notes:** `MainThreadRequired = true`. `confirm=true` required to apply; supports `dry_run`.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
# Runtime commands
|
||||
|
||||
Commands served by the Player / dev-build server. Many require a Development build running `RuntimePipelineManager` — see [Runtime setup](../runtime-setup.md). Commands marked `RuntimeOnly` are only registered in a player build.
|
||||
|
||||
### `runtime_status`
|
||||
Get comprehensive runtime application status.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `RuntimeStatusResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `quit`
|
||||
Gracefully quit the Unity application.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `exitCode` | no | `0` | Exit code for the application |
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `set_target_framerate`
|
||||
Set the target frame rate for the application.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `frameRate` | yes | `–` | Target frame rate (-1 for platform default, 0 for unlimited) |
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `set_timescale`
|
||||
Set the time scale for the application.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `scale` | yes | `–` | Time scale multiplier (0.0 to pause, 1.0 for normal speed) |
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `simulate_key`
|
||||
Simulate a keyboard key event (Input System). Drives the running app.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `key` | yes | `–` | Input System Key name, e.g. Space, W, Enter, LeftArrow. |
|
||||
| `action` | no | `press` | down \| up \| press (down+up). |
|
||||
|
||||
**Returns:** `InputSimulationResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`. Requires the Input System package (`ENABLE_INPUT_SYSTEM`); reports unavailable otherwise.
|
||||
|
||||
### `simulate_pointer`
|
||||
Simulate a mouse/pointer event at screen coordinates (Input System).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `x` | yes | `–` | Screen X in pixels (origin bottom-left). |
|
||||
| `y` | yes | `–` | Screen Y in pixels (origin bottom-left). |
|
||||
| `action` | no | `click` | move \| down \| up \| click (down+up). |
|
||||
| `button` | no | `left` | left \| right \| middle. |
|
||||
|
||||
**Returns:** `InputSimulationResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`. Requires the Input System package (`ENABLE_INPUT_SYSTEM`); reports unavailable otherwise.
|
||||
|
||||
### `log`
|
||||
Write a message to Unity console.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `message` | yes | `–` | Message to log to console |
|
||||
| `level` | no | `info` | Log level: info, warning, error |
|
||||
|
||||
**Returns:** `string`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `console`
|
||||
Get captured Unity console output (Editor or Player; supports tail, level filtering, and follow via a cursor).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `tail` | no | `100` | Maximum number of most-recent entries to return |
|
||||
| `level` | no | `log` | Minimum severity to include: log | warn | error |
|
||||
| `since` | no | `-1` | Cursor: only return entries newer than this seq. Use the 'cursor' from a previous response to follow. |
|
||||
|
||||
**Returns:** `ConsoleLogResponse`
|
||||
**Notes:** `MainThreadRequired = false`. Available in both the Editor and player builds.
|
||||
|
||||
### `eval`
|
||||
Evaluate C# code dynamically using Roslyn compiler.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `code` | yes | `–` | C# code to evaluate |
|
||||
| `timeout` | no | `5000` | Timeout in milliseconds |
|
||||
|
||||
**Returns:** `EvalResponse`
|
||||
**Notes:** `MainThreadRequired = true`. Available on both editor and runtime.
|
||||
|
||||
### `eval_file`
|
||||
Evaluate C# code read from a `.cs` file on disk. A convenience alternative to `eval` for code
|
||||
too long to pass inline — edit the file, then evaluate it. The resolved source is run through the
|
||||
same evaluation path as `eval`.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `file` | yes | `–` | Path to a `.cs` file to evaluate |
|
||||
| `timeout` | no | `5000` | Timeout in milliseconds |
|
||||
|
||||
The `file` is read on the Unity side (relative paths resolve against the Unity process working
|
||||
directory) and must end in `.cs`. A missing file, a non-`.cs` extension, or an empty file returns
|
||||
a `Bad Request`.
|
||||
|
||||
**Returns:** `EvalResponse`
|
||||
**Notes:** `MainThreadRequired = true`. Available on both editor and runtime.
|
||||
|
||||
### `reload_file`
|
||||
Compile and apply in-place [HotReload] edits from a source file.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `filename` | yes | `–` | Source file containing [HotReload] methods (e.g. Assets/Scripts/Player.cs) |
|
||||
| `timeout` | no | `30000` | Compilation timeout in milliseconds |
|
||||
| `assemblyDir` | no | `–` | Directory to save compiled assemblies to disk (optional, default is in-memory only) |
|
||||
| `pdb` | no | `false` | Emit debug symbols (portable PDB) mapped to the original source so breakpoints bind in your editor. Compiles unoptimized. |
|
||||
|
||||
**Returns:** `HotReloadResponse`
|
||||
**Notes:** `MainThreadRequired = true`. See [Hot reload](../hot-reload.md).
|
||||
|
||||
### `reload_file_override`
|
||||
Compile and apply hot reload file changes immediately.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `filename` | yes | `–` | Hot reload source file to compile (e.g. PlayerTweaks.cs) |
|
||||
| `timeout` | no | `30000` | Compilation timeout in milliseconds |
|
||||
| `assemblyDir` | no | `–` | Directory to save compiled assemblies to disk (optional, default is in-memory only) |
|
||||
|
||||
**Returns:** `HotReloadResponse`
|
||||
**Notes:** `MainThreadRequired = true`. See [Hot reload](../hot-reload.md).
|
||||
|
||||
### `hotreload_status`
|
||||
Show current hot reload registry status and statistics.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `HotReloadResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
### `cleanup_hotreload`
|
||||
Remove old hot reload DLL versions and clear registry.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `assemblyDir` | yes | `–` | Directory containing assemblies to cleanup |
|
||||
| `force_domain_reload` | no | `true` | Force Unity domain reload after cleanup |
|
||||
|
||||
**Returns:** `HotReloadResponse`
|
||||
**Notes:** `MainThreadRequired = true`, `RuntimeOnly`.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,93 @@
|
||||
# Scene commands
|
||||
|
||||
Commands for creating, opening, saving and inspecting scenes, controlling the active scene, snapshotting a scene's hierarchy, and managing the Build Settings scene list. Mutating scene operations are blocked while the editor is entering or in play mode (they fail with a recoverable error before touching any state); read-only commands are safe in play mode.
|
||||
|
||||
### `create_scene`
|
||||
Create a new scene and save it to the given path under the authoring root.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Scene path relative to the authoring root (default Assets/); the Assets/ prefix and the .unity extension are optional. e.g. Scenes/Level1 |
|
||||
| `additive` | no | `false` | Open the new scene additively alongside currently open scenes instead of replacing them. |
|
||||
| `template` | no | `empty` | Initial contents: 'empty' (default) for a blank scene, or 'default' to seed a Main Camera + Directional Light matching Unity's built-in 3D template. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `open_scene`
|
||||
Open an existing scene from the given path.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Scene path relative to the authoring root (default Assets/); the Assets/ prefix and the .unity extension are optional. |
|
||||
| `additive` | no | `false` | Open additively alongside currently open scenes instead of replacing them. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `save_scene`
|
||||
Save an open scene. Saves the active scene when no path is given.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | no | `–` | Path of the open scene to save (authoring-root relative; Assets/ prefix and .unity optional). Omit to save the active scene. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `save_all`
|
||||
Save all open scenes that have unsaved changes.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `list_open_scenes`
|
||||
List all currently open scenes with their load/active/dirty state.
|
||||
|
||||
No parameters.
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
### `set_active_scene`
|
||||
Set which open scene is the active scene (new objects are created in the active scene).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Path of an already-open scene to make active (authoring-root relative; Assets/ prefix and .unity optional). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `get_scene_hierarchy`
|
||||
Return the GameObject tree of an open scene (or the active scene). Each node carries instanceId + hierarchyPath usable by GameObject commands.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | no | `–` | Path of the open scene to snapshot (authoring-root relative; Assets/ prefix and .unity optional). Omit for the active scene. |
|
||||
|
||||
**Returns:** `SceneHierarchy`
|
||||
|
||||
### `add_scene_to_build`
|
||||
Add a scene to the Build Settings scene list (idempotent). Optionally enable it.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Scene path to add (authoring-root relative; Assets/ prefix and .unity optional). |
|
||||
| `enabled` | no | `true` | Whether the scene is enabled in the build list. |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
### `remove_scene_from_build`
|
||||
Remove a scene from the Build Settings scene list (idempotent).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `path` | yes | – | Scene path to remove (authoring-root relative; Assets/ prefix and .unity optional). |
|
||||
|
||||
**Returns:** `object`
|
||||
**Notes:** Blocked during Play mode.
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,55 @@
|
||||
# Script commands
|
||||
|
||||
Commands for creating C# script files, attaching MonoBehaviours to GameObjects, and reading/writing serialized fields. Writing a `.cs` file does not make its type available — Unity must import and compile it (a domain reload) first. The flow is: `create_script` → `recompile` → poll `recompile_status` (until completed/up_to_date) → `attach_script`.
|
||||
|
||||
### `create_script`
|
||||
Create a new C# script (default base class MonoBehaviour) from a template under the authoring root. NOTE: the type does not exist until a recompile completes — to attach it, call recompile, poll recompile_status, then attach_script.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `name` | yes | – | Class/file name without extension, e.g. PlayerController. Must be a valid C# identifier. |
|
||||
| `path` | no | `–` | Folder (relative to the authoring root; the Assets/ prefix is optional) to write the .cs into. Defaults to the authoring root. |
|
||||
| `namespace` | no | `–` | Optional namespace to wrap the class in. Omit for the global namespace. |
|
||||
| `base_class` | no | `MonoBehaviour` | Base class to derive from. Defaults to MonoBehaviour. |
|
||||
| `overwrite` | no | `false` | Overwrite the file if it already exists. Defaults to false (an existing file is an error). |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Does not trigger a recompile; the created type is not usable until a recompile completes (poll `recompile_status`).
|
||||
|
||||
### `attach_script`
|
||||
Add a MonoBehaviour to a GameObject by its (compiled) type name OR by its script asset path. Provide exactly one of 'type' or 'script'. If the type isn't compiled yet, returns a recoverable error: recompile, poll recompile_status, then retry.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Reference to the GameObject to add the component to (globalId/path/guid/instanceId/hierarchyPath). |
|
||||
| `type` | no | `–` | Component type name to add, e.g. PlayerController or Game.Player.PlayerController. Must already be compiled. Mutually exclusive with 'script'. |
|
||||
| `script` | no | `–` | Script asset path, e.g. 'Assets/Pool/Scripts/CueShooter.cs'. The backing class is resolved via MonoScript.GetClass(), so the class name may differ from the filename. Mutually exclusive with 'type'. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able. Provide exactly one of `type` or `script`. A not-yet-compiled type returns a recoverable error (recompile, poll `recompile_status`, then retry).
|
||||
|
||||
### `set_serialized_field`
|
||||
Set a serialized field on a component/asset. Supports primitives, enums, Vector/Color/Rect/Bounds, object references (value = an ObjectRef: asset by guid/fileId/path or scene object by instanceId/hierarchyPath), and array elements via 'name.Array.data[i]' (or 'name.Array.size' to resize).
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Reference to the component or asset to modify (globalId/path/guid/instanceId/hierarchyPath). May be a GameObject when 'component' is given. |
|
||||
| `field` | yes | – | SerializedProperty path, e.g. 'speed', 'settings.speed', or 'waypoints.Array.data[0]'. |
|
||||
| `value` | yes | – | JSON value to assign. For object references pass an ObjectRef object (or null to clear). For enums pass the value name. |
|
||||
| `component` | no | `–` | Component type name on the target GameObject (e.g. 'Rigidbody'). Use when 'target' is a GameObject; omit when 'target' is already a component handle. |
|
||||
|
||||
**Returns:** `AuthoringResult`
|
||||
**Notes:** Undo-able.
|
||||
|
||||
### `get_serialized_fields`
|
||||
Read serialized fields of a component/asset. Returns each top-level field's name, type and value (object references are returned as re-usable handles). Pass 'field' to read a single SerializedProperty path.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `target` | yes | – | Reference to the component or asset to read (globalId/path/guid/instanceId/hierarchyPath). May be a GameObject when 'component' is given. |
|
||||
| `field` | no | `–` | Optional single SerializedProperty path to read (e.g. 'speed' or 'items.Array.data[0]'). Omit to read all top-level fields. |
|
||||
| `component` | no | `–` | Component type name on the target GameObject (e.g. 'Rigidbody'). Use when 'target' is a GameObject; omit when 'target' is already a component handle. |
|
||||
|
||||
**Returns:** `object`
|
||||
|
||||
See [Creating commands](../creating-commands.md) and [Connectivity](../connectivity.md).
|
||||
@@ -0,0 +1,178 @@
|
||||
# Connectivity
|
||||
|
||||
How a client reaches a running Unity instance: the loopback-only HTTP servers, their port ranges, the port descriptor file used for discovery, and the bearer-token authentication every request must carry.
|
||||
|
||||
The rest of this page covers the implementation. If you just want to connect, start with the two sections below.
|
||||
|
||||
## Connecting to a running Editor
|
||||
|
||||
Connections go through the `unity` CLI. Run `unity command` with no command name to connect to a Unity instance and list its available commands:
|
||||
|
||||
```bash
|
||||
# Auto-discover a Unity instance from the current directory
|
||||
unity command
|
||||
|
||||
# Connect to a specific project
|
||||
unity command --project-path /path/to/your/unity/project
|
||||
```
|
||||
|
||||
Once connected, run any command by name, e.g. `unity command editor_status`.
|
||||
|
||||
## Connecting to a running Player (game)
|
||||
|
||||
To target a running development Player instead of the Editor, use `--runtime` (by process name) or `--runtime-path` (by the location of the runtime port file). These options go **after** `command` and **before** the command name:
|
||||
|
||||
```bash
|
||||
# By Player process/executable name
|
||||
unity command --runtime MyGame.exe runtime_status
|
||||
|
||||
# By the folder/bundle where the runtime port file lives
|
||||
unity command --runtime-path "C:\Builds\MyGame" runtime_status # Windows: next to the .exe
|
||||
unity command --runtime-path "/Users/me/Builds/MyGame.app" runtime_status # macOS: the .app bundle
|
||||
```
|
||||
|
||||
> The Runtime server only runs in a **development Player build** with the runtime manager enabled — see [Runtime connection & setup](runtime-setup.md).
|
||||
|
||||
## Finding the port in the Unity logs
|
||||
|
||||
The [port descriptor file](#port-descriptor-file) is the primary discovery channel, but the server also reports itself to the Unity log when it starts and stops — useful when you can't read the descriptor file directly. Look for `Pipeline`-prefixed lines.
|
||||
|
||||
- **Runtime (Player)** — logs its port **and** the descriptor file location on start, and a line on stop:
|
||||
|
||||
```
|
||||
Pipeline: Runtime server started successfully on port 7901
|
||||
Pipeline: Runtime descriptor written to /path/to/MyGame/.unity-pipeline-runtime-port
|
||||
Pipeline: Runtime server stopped
|
||||
```
|
||||
|
||||
- **Editor** — logs its port when the server is (re)started from the **Pipeline ▸ Start Server** menu or re-opened by its watchdog (`Pipeline Server started on port 7801`). Its descriptor always lives at the fixed `Library/Pipeline/.unity-pipeline-port` path.
|
||||
|
||||
### Where the logs live
|
||||
|
||||
**Editor log** (`Editor.log`):
|
||||
|
||||
| OS | Path |
|
||||
|----|------|
|
||||
| Windows | `C:\Users\<user>\AppData\Local\Unity\Editor\Editor.log` |
|
||||
| macOS | `~/Library/Logs/Unity/Editor.log` |
|
||||
|
||||
**Player log** (`Player.log`):
|
||||
|
||||
| OS | Path |
|
||||
|----|------|
|
||||
| Windows | `C:\Users\<user>\AppData\LocalLow\<company>\<product>\Player.log` |
|
||||
| macOS | `~/Library/Logs/<company>/<product>/Player.log` |
|
||||
|
||||
(`<company>` and `<product>` are the project's **Company Name** and **Product Name** from Player Settings.)
|
||||
|
||||
## Loopback-only binding
|
||||
|
||||
Both the Editor and Runtime servers bind to the **IPv4 loopback** (`127.0.0.1`) — plus the `localhost` hostname for compatibility:
|
||||
|
||||
```csharp
|
||||
if (Socket.OSSupportsIPv4)
|
||||
m_HttpListener.Prefixes.Add($"http://127.0.0.1:{m_Port}/");
|
||||
m_HttpListener.Prefixes.Add($"http://localhost:{m_Port}/");
|
||||
```
|
||||
|
||||
The server is never exposed on a routable interface — it is reachable only from the same machine.
|
||||
|
||||
Clients should connect to **`127.0.0.1`** explicitly rather than `localhost`. Unity's Mono `HttpListener` only reliably serves the IPv4 loopback: a request arriving over the IPv6 loopback (`::1`) is answered with `400` because Mono mis-parses the bracketed `[::1]` host. Since `localhost` resolves to `::1` or `127.0.0.1` non-deterministically (notably on Windows with Node's default DNS order), dialing `localhost` caused intermittent connection failures — dialing `127.0.0.1` avoids the IPv6 path entirely.
|
||||
|
||||
In addition, the server refuses any request that carries an `Origin` header (legitimate CLI/CI clients never send one), which blocks a browser page from reaching the local server and short-circuits CORS preflights.
|
||||
|
||||
## Port ranges
|
||||
|
||||
Each server type picks the first free port in its range (or you can pin one explicitly):
|
||||
|
||||
| Server | Production range | Test range |
|
||||
|--------|------------------|------------|
|
||||
| **Editor** | `7800`–`7849` | `7850`–`7899` |
|
||||
| **Runtime** (Player) | `7900`–`7949` | `7950`–`7999` |
|
||||
|
||||
If no port in the range is free, startup throws (`No available ports in range …`).
|
||||
|
||||
## Port Descriptor File
|
||||
|
||||
When a server starts, it writes a small JSON **instance descriptor** so clients can discover it. This is the only discovery channel — there is no broadcast or registry.
|
||||
|
||||
| Server | Descriptor path |
|
||||
|--------|-----------------|
|
||||
| **Editor** | `<projectPath>/Library/Pipeline/.unity-pipeline-port` |
|
||||
| **Runtime** | `<workingDirectory>/.unity-pipeline-runtime-port` |
|
||||
|
||||
The Editor descriptor lives under the git-ignored `Library/` folder. The file is created with permissions restricted to the current user (it carries the auth token). The server rewrites it on every heartbeat to refresh `lastHeartbeat`, and deletes it on shutdown.
|
||||
|
||||
The Runtime descriptor is written next to the Player, at `{Application.dataPath}/..`:
|
||||
|
||||
- **Windows / Linux** — beside the executable, e.g. `C:\Builds\MyGame\.unity-pipeline-runtime-port`.
|
||||
- **macOS** — `Application.dataPath` is `<Game>.app/Contents`, so the descriptor lands at the **`.app` bundle root**: `MyGame.app/.unity-pipeline-runtime-port`. (The file is inside the `.app` bundle.) This is why `unity command --runtime-path` takes the `.app` bundle path on macOS — see [Runtime connection & setup](runtime-setup.md).
|
||||
|
||||
> Test servers do **not** write a descriptor (they override `WritesDescriptor => false`) — the test already knows its port, so it never clobbers the live server's file. See [Tests architecture](testing.md).
|
||||
|
||||
### Editor descriptor fields
|
||||
|
||||
```json
|
||||
{
|
||||
"pid": 12345,
|
||||
"port": 7800,
|
||||
"projectPath": "/path/to/Project",
|
||||
"projectName": "Project",
|
||||
"unityVersion": "6000.x.y",
|
||||
"mode": "editor",
|
||||
"startedAt": "2026-06-25T10:00:00Z",
|
||||
"lastHeartbeat": "2026-06-25T10:05:00Z",
|
||||
"evalToken": "<base64 token>"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `pid` | Process id of the Unity Editor. |
|
||||
| `port` | Port the server is listening on. |
|
||||
| `projectPath` | Absolute path to the Unity project. |
|
||||
| `projectName` | Project folder name. |
|
||||
| `unityVersion` | Editor version string. |
|
||||
| `mode` | `"editor"` or `"batchmode"`. |
|
||||
| `startedAt` | When the instance started (UTC). |
|
||||
| `lastHeartbeat` | Last heartbeat (UTC), refreshed on status calls. |
|
||||
| `evalToken` | Bearer token for authenticating requests. |
|
||||
|
||||
### Runtime descriptor fields
|
||||
|
||||
The runtime descriptor shares `pid`, `port`, `unityVersion`, `startedAt`, `lastHeartbeat`, and `evalToken`, and adds:
|
||||
|
||||
| Field | Meaning |
|
||||
|-------|---------|
|
||||
| `platform` | Unity runtime platform (e.g. `WindowsPlayer`). |
|
||||
| `buildGuid` | Unique build identifier (`Application.buildGUID`). |
|
||||
| `workingDirectory` | Directory the Player is running from. |
|
||||
|
||||
(The runtime descriptor carries `platform`/`buildGuid`/`workingDirectory` in place of the editor's `projectPath`/`projectName`/`mode`.)
|
||||
|
||||
## Authentication
|
||||
|
||||
Every request must authenticate with a bearer token:
|
||||
|
||||
```
|
||||
Authorization: Bearer <evalToken>
|
||||
```
|
||||
|
||||
- The server **generates the token at startup** (`SecurityTokenManager.GetOrCreateToken()` — 256 bits of CSPRNG output, base64-encoded). In the Editor the token is persisted in `SessionState`, so it **survives domain reloads** within an editor session (recompiles, entering play mode) — long-lived clients (MCP sessions, IDE integrations) keep working instead of getting `401` after every reload. It is regenerated only when the Editor **restarts**, or on an explicit rotation (`SecurityTokenManager.ClearCache()` / `RotateToken()`). Player builds use a per-process token.
|
||||
- The token is published in the descriptor's `evalToken` field. The descriptor is **re-advertised with the live token on every heartbeat**, so the port file never advertises a token the server would reject (e.g. after a reload or rotation).
|
||||
- The server validates the bearer token on **every** request (before routing) using a constant-time comparison. A missing or wrong token returns `401 Unauthorized`.
|
||||
|
||||
## Discovering and calling an instance
|
||||
|
||||
A client connects by:
|
||||
|
||||
1. Reading the descriptor file (editor: `Library/Pipeline/.unity-pipeline-port`).
|
||||
2. Taking the `port` and `evalToken` from it.
|
||||
3. Sending requests to `http://127.0.0.1:<port>/...` with `Authorization: Bearer <evalToken>`.
|
||||
|
||||
Endpoints exposed by the server include `/api/status`, `/api/editor_status`, `/api/commands` (lists available commands), `/api/exec` (POST — runs a command), and `/api/test-status`.
|
||||
|
||||
## See also
|
||||
|
||||
- [Runtime connection & setup](runtime-setup.md) — enabling the server in a Player build.
|
||||
- [Creating commands](creating-commands.md) — authoring the commands clients call.
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
# Creating commands
|
||||
|
||||
A *command* is a `static` method that the Pipeline server can invoke over HTTP. The method's accessibility does not matter — `public`, `internal`, and `private` static methods can all be registered. This page covers the command-authoring API: how to declare a command, describe its parameters, return a result, and have it discovered automatically.
|
||||
|
||||
## The handler + response pattern
|
||||
|
||||
Authoring a command has two halves:
|
||||
|
||||
1. **The handler** — your `static` method, tagged `[CliCommand]`. It does the work and returns a value.
|
||||
2. **The response** — the server wraps whatever your handler returns in a [`CommandExecutionResponse`](#the-commandexecutionresponse-envelope) and serializes it to JSON for the client.
|
||||
|
||||
You never build the HTTP response yourself. Return a `string`, a number, an anonymous object, a typed model, or `null`; the server takes care of the envelope, timing, and error reporting.
|
||||
|
||||
## Declaring a command
|
||||
|
||||
Tag a `static` method with `[CliCommand]` (the examples below use `public`, but any accessibility works):
|
||||
|
||||
```csharp
|
||||
[CliCommand("name", "description", MainThreadRequired = true, RuntimeOnly = false)]
|
||||
public static <ReturnType> Handler(...);
|
||||
```
|
||||
|
||||
| Argument | Meaning |
|
||||
|----------|---------|
|
||||
| `name` | Unique command name used by the client (`unity command <name>`). |
|
||||
| `description` | Human-readable text shown in help and the `/api/commands` listing. |
|
||||
| `MainThreadRequired` | Whether the handler must run on Unity's main thread. **Default `true`.** |
|
||||
| `RuntimeOnly` | Whether the command is hidden from an Editor server's command listing. **Default `false`.** |
|
||||
|
||||
The method **must be `static`**, but its accessibility does not matter: `public`, `internal`, and `private` static methods can all be registered. `CommandRegistry` invokes handlers through reflection, so a `private` handler runs exactly like a `public` one. Only a non-static (instance) method fails to register — `CommandRegistry` skips it and logs a warning.
|
||||
|
||||
### Describing parameters
|
||||
|
||||
Tag each parameter with `[CliArg]`:
|
||||
|
||||
```csharp
|
||||
[CliArg("name", "description", Required = false, DefaultValue = null)]
|
||||
```
|
||||
|
||||
| Property | Meaning |
|
||||
|----------|---------|
|
||||
| `name` | Parameter name as it appears in client arguments (`--name value`). |
|
||||
| `description` | Human-readable description for help text. |
|
||||
| `Required` | Whether the parameter must be supplied. Defaults to `false` — but if the parameter has no C# default value it is treated as required. |
|
||||
| `DefaultValue` | Value used when the client omits the parameter (a C# default value takes precedence). |
|
||||
|
||||
`[CliArg]` is optional metadata. A parameter without it still works: its name defaults to the C# parameter name and `Required` defaults to "does this parameter lack a C# default value?".
|
||||
|
||||
## Worked example 1 — returning a string
|
||||
|
||||
A command can return a plain `string`. The server places it in the response `result` field.
|
||||
|
||||
```csharp
|
||||
using Unity.Pipeline.Commands;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public static class PlayModeCommands
|
||||
{
|
||||
[CliCommand("editor_play", "Enter Unity Editor play mode")]
|
||||
public static string EnterPlayMode()
|
||||
{
|
||||
if (EditorApplication.isPlaying)
|
||||
return "Already in play mode";
|
||||
|
||||
EditorApplication.isPlaying = true;
|
||||
return "Entered play mode";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Calling `editor_play` yields a `CommandExecutionResponse` whose `result` is `"Entered play mode"`.
|
||||
|
||||
## Worked example 2 — returning a response model
|
||||
|
||||
For richer results, return a model. Returning a type that extends `CommandExecutionResponse` (like `EvalResponse`) lets you populate response fields directly; you can also return any plain serializable model (like `AuthoringResult`) and let the server wrap it.
|
||||
|
||||
```csharp
|
||||
using Unity.Pipeline.Commands;
|
||||
using Unity.Pipeline.Models;
|
||||
using Unity.Pipeline.Compilation;
|
||||
|
||||
public static class CodeEvalCommand
|
||||
{
|
||||
[CliCommand("eval", "Evaluate C# code dynamically using Roslyn compiler", MainThreadRequired = true)]
|
||||
public static EvalResponse EvaluateCode(
|
||||
[CliArg("code", "C# code to evaluate", Required = true)] string code,
|
||||
[CliArg("timeout", "Timeout in milliseconds")] int timeout = 5000)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
return EvalResponse.EvalFailure("Bad Request", "Code parameter is required and cannot be empty");
|
||||
|
||||
var result = EvalCodeCompiler.CompileAndExecuteOnMainThread(code, timeout, null);
|
||||
return result ?? EvalResponse.EvalFailure("Unknown Error", "Compilation returned null result");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`EvalResponse` adds `output` and `diagnostics` on top of the standard envelope. Another common shape is a domain model such as `AuthoringResult` — the canonical identity (asset path, GUID, instance id, hierarchy path) of an object a command created, returned so the client can reference it in a follow-up call.
|
||||
|
||||
## Structured (multi-field) parameters
|
||||
|
||||
When a command needs a structured argument with several fields, don't spread them across many `[CliArg]` parameters — declare a small DTO that implements `IStructuredCommandInput` and take it as a single parameter. The type is advertised to clients as a nested JSON **object** schema in `GET /api/commands` (instead of collapsing to `string`), and the value is deserialized automatically via Newtonsoft — no extra wiring.
|
||||
|
||||
```csharp
|
||||
[CliCommand("set_time_settings", "Change Time settings. Requires confirm=true; use dry_run to preview.")]
|
||||
public static ProjectSettingsResponse Set(
|
||||
[CliArg("settings", "Fields to change; omitted fields are left unchanged.")] TimeSettingsInput settings = null,
|
||||
[CliArg("confirm", "Apply the change. Without it the call is refused.")] bool confirm = false,
|
||||
[CliArg("dry_run", "Preview the change without applying it.")] bool dryRun = false)
|
||||
{ /* ... */ }
|
||||
|
||||
public class TimeSettingsInput : IStructuredCommandInput
|
||||
{
|
||||
[CliArg("fixedDeltaTime", "Fixed timestep in seconds (e.g. 0.02).")]
|
||||
public float? FixedDeltaTime { get; set; }
|
||||
|
||||
[CliArg("timeScale", "Time scale (1 = real-time).")]
|
||||
public float? TimeScale { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
`JsonSchemaGenerator` reflects over the type's public, writable fields and properties to emit `{ "type": "object", "properties": { ... } }`, recursing into nested `IStructuredCommandInput` members and arrays/lists of them. Member metadata mirrors command parameters:
|
||||
|
||||
- `[CliArg(name, description, Required = ...)]` controls the property name, description, and whether it appears in the schema's `required` array.
|
||||
- Without a `[CliArg]`, the member (or its Newtonsoft `[JsonProperty]`) name is used and it is optional. Use nullable types (`float?`) for "omitted = leave unchanged" semantics.
|
||||
- `[JsonIgnore]` members are omitted from the schema.
|
||||
|
||||
`[CliArg]` is valid on parameters, fields, and properties, so the same attribute annotates DTO members. Most commands that take an `IStructuredCommandInput` are mutations — pair the DTO with `confirm`/`dry_run` and follow the [safety conventions](safety-and-mutations.md) (inline gate + `AuthoringUndoScope`).
|
||||
|
||||
## The `CommandExecutionResponse` envelope
|
||||
|
||||
Whatever your handler returns, the client receives a `CommandExecutionResponse`:
|
||||
|
||||
| Field | Type | Meaning |
|
||||
|-------|------|---------|
|
||||
| `success` | `bool` | Whether the command ran without throwing. |
|
||||
| `command` | `string` | The command name. |
|
||||
| `result` | `object` | Your handler's return value (a string, model, anonymous object, or `null`). |
|
||||
| `executionTimeMs` | `long?` | How long the command took. |
|
||||
| `error` | `string` | Error summary when `success` is `false`. |
|
||||
|
||||
If your handler throws, the server catches it and returns a failure envelope with `success = false` and the exception message in `error` — you do not need to catch-and-wrap yourself unless you want a tailored message.
|
||||
|
||||
## `MainThreadRequired`
|
||||
|
||||
- **Default: `true`.** Most Unity APIs (scene, GameObject, asset, play-mode access) must run on the main thread. The server marshals these handlers onto the main thread via its dispatcher.
|
||||
- **Set `false` only** for handlers that are thread-safe and read-only / pollable (e.g. a status or buffer-read command). These run on a background thread so they never block the main thread or deadlock against a busy editor.
|
||||
|
||||
When in doubt, leave it `true`.
|
||||
|
||||
## `RuntimeOnly`
|
||||
|
||||
- **Default: `false`** — the command is advertised in an Editor server's `/api/commands` listing.
|
||||
- **Set `true`** to hide a command from the Editor command listing. It remains **executable**; it is simply not advertised when a client is connected to an Editor (Runtime/Player servers still list it). Use this for commands that only make sense against a running Player.
|
||||
|
||||
## Discovery
|
||||
|
||||
Commands are discovered by `CommandRegistry`, which scans for `[CliCommand]`-tagged methods through a pluggable `ICommandDiscovery`:
|
||||
|
||||
- In the **Editor**, `TypeCacheCommandDiscovery` provides fast `TypeCache`-based discovery.
|
||||
- In a **Player**, the registry falls back to reflection over loaded assemblies.
|
||||
|
||||
Results are cached until the next domain reload. **A newly added command becomes available after the next recompile** — no registration call is needed; just declare it and recompile.
|
||||
|
||||
## Minimal custom command template
|
||||
|
||||
```csharp
|
||||
using Unity.Pipeline.Commands;
|
||||
|
||||
public static class MyCommands
|
||||
{
|
||||
[CliCommand("my_command", "What this command does")]
|
||||
public static object MyCommand(
|
||||
[CliArg("text", "Some input", Required = true)] string text,
|
||||
[CliArg("count", "How many times")] int count = 1)
|
||||
{
|
||||
// Do work on the main thread (MainThreadRequired defaults to true).
|
||||
return new { echoed = text, count }; // anonymous object → response.result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Recompile, then invoke it from your client (`unity command my_command --text hello --count 3`).
|
||||
|
||||
## See also
|
||||
|
||||
- [Command reference](commands/runtime.md)
|
||||
- [Connectivity](connectivity.md) — how clients reach the server and authenticate.
|
||||
@@ -0,0 +1,145 @@
|
||||
# Hot reload
|
||||
|
||||
Apply edited C# to running code without restarting Play Mode or rebuilding the Player. Two flavors are supported: **in-place** reload of a tagged method body, and **override** reload that routes a method through a separately-compiled replacement.
|
||||
|
||||
Hot reload runs in **Editor Play Mode and Mono standalone development builds only** — not IL2CPP. Like code eval, it is gated behind `#if UNITY_EDITOR || (UNITY_STANDALONE && DEBUG)`.
|
||||
|
||||
## Flavor 1 — in-place (`reload_file`)
|
||||
|
||||
Tag the method you want to be reloadable with `[HotReload]`, then edit its body and apply the file. The running instance picks up the new body.
|
||||
|
||||
```csharp
|
||||
using Unity.Pipeline.HotReload;
|
||||
using UnityEngine;
|
||||
|
||||
public class Spinner : MonoBehaviour
|
||||
{
|
||||
public float rotationSpeed = 90f;
|
||||
|
||||
[HotReload]
|
||||
void Update()
|
||||
{
|
||||
transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Edit the body of `Update`, then apply it:
|
||||
|
||||
```bash
|
||||
unity command reload_file "<absolute path>/Spinner.cs"
|
||||
|
||||
# Emit debug symbols so breakpoints bind (compiles unoptimized):
|
||||
unity command reload_file "<absolute path>/Spinner.cs" --pdb
|
||||
```
|
||||
|
||||
`reload_file` parameters:
|
||||
|
||||
| Arg | Default | Meaning |
|
||||
|-----|---------|---------|
|
||||
| `filename` | *(required)* | Source file containing `[HotReload]` methods. |
|
||||
| `timeout` | `30000` | Compilation timeout (ms). |
|
||||
| `assemblyDir` | `null` | Optional directory to also save the compiled assembly to disk (default: in-memory only). |
|
||||
| `pdb` | `false` | Emit a portable PDB mapped to the original source so debugger breakpoints bind. Compiles unoptimized. |
|
||||
|
||||
**Constraints (in-place):** the `[HotReload]` method must be a **`void` instance method** that is **`public`**, and reload works on **Mono only**. The CodeGen ILPostProcessor skips static methods and value-returning methods at build time (with a warning), so only matching methods are weaved for dispatch.
|
||||
|
||||
## Flavor 2 — override (`reload_file_override`)
|
||||
|
||||
When you want to swap behavior from a *separate* file (leaving the original untouched), tag the method with `[HotReloadWithOverrides]` and route it through `HotReloadHelper.ExecuteWithHotReload`:
|
||||
|
||||
```csharp
|
||||
using Unity.Pipeline.HotReload;
|
||||
using UnityEngine;
|
||||
|
||||
public class BossController : MonoBehaviour
|
||||
{
|
||||
[HotReloadWithOverrides]
|
||||
void Update()
|
||||
{
|
||||
HotReloadHelper.ExecuteWithHotReload(this, "Update", OriginalUpdate);
|
||||
}
|
||||
|
||||
public void OriginalUpdate()
|
||||
{
|
||||
transform.Rotate(45 * Time.deltaTime, 0, 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Put the tweaked behavior in a **separate file** as a **`public static` method** tagged `[HotReloadOverrideMethod("Type.Method")]`. The override **takes the target instance as its first parameter**:
|
||||
|
||||
```csharp
|
||||
// BossOverrides.cs — a separate file
|
||||
using Unity.Pipeline.HotReload;
|
||||
using UnityEngine;
|
||||
|
||||
public static class BossOverrides
|
||||
{
|
||||
[HotReloadOverrideMethod("BossController.Update")]
|
||||
public static void TweakedUpdate(BossController instance)
|
||||
{
|
||||
instance.transform.Rotate(0, 90 * Time.deltaTime, 0); // new behaviour
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Apply the override file:
|
||||
|
||||
```bash
|
||||
unity command reload_file_override "<absolute path>/BossOverrides.cs"
|
||||
```
|
||||
|
||||
`reload_file_override` parameters:
|
||||
|
||||
| Arg | Default | Meaning |
|
||||
|-----|---------|---------|
|
||||
| `filename` | *(required)* | The override source file to compile. |
|
||||
| `timeout` | `30000` | Compilation timeout (ms). |
|
||||
| `assemblyDir` | `null` | Optional directory to also save the compiled assembly to disk (default: in-memory only). |
|
||||
|
||||
The override method's signature must be `public static <ReturnType> Name(<TargetType> instance, ...)` — return type and trailing parameters matching the original. Do **not** redeclare the target type in the override file (a common cause of "signature mismatch"). Until an override is applied, `ExecuteWithHotReload` calls `OriginalUpdate`; once applied, dispatch routes to the override.
|
||||
|
||||
`ExecuteWithHotReload` has matching overloads for both value-returning (`Func<object>`) and void (`Action`) originals:
|
||||
|
||||
```csharp
|
||||
public static object ExecuteWithHotReload<T>(T instance, string methodName, Func<object> originalMethod, params object[] parameters);
|
||||
public static void ExecuteWithHotReload<T>(T instance, string methodName, Action originalMethod, params object[] parameters);
|
||||
```
|
||||
|
||||
## Supporting commands
|
||||
|
||||
- `hotreload_status` — show registry stats (which methods have overrides registered).
|
||||
- `cleanup_hotreload` — remove old hot-reload assemblies and clear the registry.
|
||||
|
||||
## Architecture
|
||||
|
||||
The pipeline that turns an edited source file into running code:
|
||||
|
||||
1. **Compile (Roslyn, in-memory).** `RoslynCompilationService.Compile` parses and compiles the source to a `DynamicallyLinkedLibrary` entirely in memory — IL bytes in one `MemoryStream`, and (when `pdb`/`EmitDebugInformation` is requested) a **portable PDB** in another. **Nothing is written to disk** by default. When emitting debug info it compiles unoptimized (`OptimizationLevel.Debug`) so sequence points survive and breakpoints can bind.
|
||||
|
||||
2. **Load into the running AppDomain.** The IL (and optional PDB) bytes are loaded via `PipelineUtils.LoadFromBytes`, which selects the load mechanism by Unity version:
|
||||
|
||||
```csharp
|
||||
public static Assembly LoadFromBytes(byte[] bytes, byte[] pdb = null)
|
||||
{
|
||||
#if UNITY_6000_5_OR_NEWER
|
||||
return UnityEngine.Assemblies.CurrentAssemblies.LoadFromBytes(bytes, pdb);
|
||||
#else
|
||||
return System.Reflection.Assembly.Load(bytes, pdb);
|
||||
#endif
|
||||
}
|
||||
```
|
||||
|
||||
On Unity 6000.5+ it uses Unity's `CurrentAssemblies.LoadFromBytes`; on older versions it falls back to `Assembly.Load(bytes, pdb)`. Either way the freshly compiled code becomes a **sibling assembly** loaded next to the original in the live AppDomain.
|
||||
|
||||
3. **Dispatch.** Calls are routed through `HotReloadRegistry`. The registry keys dispatch on `TypeName.MethodName`; when an override is registered for that id, `TryInvokeHotReload` invokes it with the instance as the first argument (marshaling to the main thread via the injected `Dispatcher` if the override requires it). If no override is registered, the original code runs.
|
||||
|
||||
4. **In-place weaving (CodeGen).** For the in-place flavor, the **`HotReloadInPlaceILPostProcessor`** (built on Mono.Cecil, in the `Unity.Pipeline.CodeGen` assembly) weaves a dispatch prologue into every `[HotReload]` method **at build/compile time**. That prologue checks the registry for a reloaded body and calls it instead of the original — which is how an edited `[HotReload]` body takes effect without changing the call sites. The post-processor enforces the void-instance-method constraint, skipping (with a warning) any static or value-returning `[HotReload]` method.
|
||||
|
||||
Because hot reload depends on Mono's ability to load a sibling assembly and dispatch into it, it is limited to **Editor Play Mode and Mono standalone dev builds — not IL2CPP**.
|
||||
|
||||
## See also
|
||||
|
||||
- [Runtime connection & setup](runtime-setup.md) — enabling hot reload in a Player build.
|
||||
- [Command reference](commands/runtime.md)
|
||||
@@ -0,0 +1,267 @@
|
||||
# Pipeline Documentation
|
||||
|
||||
`com.unity.pipeline` lets a client — CLI, CI, or an agent — drive a running Unity Editor (or a
|
||||
development Player) over a local HTTP API by executing registered commands. This is the documentation
|
||||
index; the [README](../README.md) has the full narrative overview, install steps, and CLI walkthrough.
|
||||
|
||||
## Guides
|
||||
|
||||
| Page | What it covers |
|
||||
|------|----------------|
|
||||
| [Creating commands](creating-commands.md) | The command-authoring API: `[CliCommand]`/`[CliArg]`, the handler + response pattern, and the `MainThreadRequired` / `RuntimeOnly` flags. |
|
||||
| [Creating authoring commands](authoring-commands.md) | Building content-authoring commands: the authoring root sandbox, `ObjectRef` in / `AuthoringResult` out, and undo grouping — with a worked example for a new content type. |
|
||||
| [Safety & mutations](safety-and-mutations.md) | Conventions shared by state-changing commands: the `confirm`/`dry_run` gate, Undo grouping via `AuthoringUndoScope`, and the path sandbox. |
|
||||
| [Connectivity](connectivity.md) | How servers bind localhost, the port ranges, the port/descriptor file, and the bearer-token auth workflow. |
|
||||
| [Runtime connection & setup](runtime-setup.md) | Running the server in a development Player via `RuntimePipelineManager` and the dev-build gating. |
|
||||
| [Hot reload](hot-reload.md) | The two hot-reload flavors (in-place and override) with examples, plus the Roslyn / in-memory-assembly architecture. |
|
||||
| [Tests architecture](testing.md) | Writing command tests via `PipelineClient` (over HTTP) and via direct command calls. |
|
||||
|
||||
## Command reference
|
||||
|
||||
| Page | Commands |
|
||||
|------|----------|
|
||||
| [Asset & file commands](commands/assets-and-files.md) | Create / import / move / copy / rename / delete / find assets, import settings, folders, text files. |
|
||||
| [Scene commands](commands/scenes.md) | Create / open / save scenes, build-settings list, hierarchy, active scene. |
|
||||
| [GameObject & component commands](commands/gameobjects-and-components.md) | Create / find / transform / parent / tag / layer GameObjects; add / remove / read / set components. |
|
||||
| [Prefab commands](commands/prefabs.md) | Create, instantiate, variant, apply / revert overrides, unpack, edit prefab contents. |
|
||||
| [Script commands](commands/scripts.md) | Create and attach scripts; get / set serialized fields. |
|
||||
| [Animation commands](commands/animation.md) | Create AnimationClips (+ curves), AnimatorControllers (parameters / layers / states / transitions), and Timeline assets. |
|
||||
| [Material & shader commands](commands/materials.md) | Read / set material shader properties and keywords; list and introspect shaders. |
|
||||
| [Baking commands](commands/baking.md) | Bake / clear lighting, NavMesh, and occlusion culling (async — poll the matching `*_bake_status`). |
|
||||
| [Navigation & selection commands](commands/navigation.md) | Read / set the Editor selection; run Unity Search queries. |
|
||||
| [Capture commands](commands/capture.md) | Screenshot the game / scene view and capture UI Toolkit visual elements. |
|
||||
| [Build, compilation & test commands](commands/build-and-compilation.md) | Build the Player, switch build target, read/write build settings, list targets/profiles, recompile scripts, and run tests (async — poll the matching `*_status`). |
|
||||
| [Project settings commands](commands/project-settings.md) | Read / change Audio, Graphics, Input, Physics, Player, Quality, Tags & Layers, and Time settings (`get_*`/`set_*`, gated by `confirm`/`dry_run`). |
|
||||
| [Package Manager commands](commands/package-manager.md) | List / search / add / remove / resolve UPM packages and poll operation status. |
|
||||
| [Editor lifecycle & observability commands](commands/editor-lifecycle-and-observability.md) | Play / stop / pause, focus, menus, screenshots, console logs, performance stats, authoring root. |
|
||||
| [Runtime commands](commands/runtime.md) | Player-side commands: status, quit, frame rate, time scale, log, console, eval, hot reload. |
|
||||
|
||||
## Command index
|
||||
|
||||
Every available command, grouped by area. Each name links to its full reference (parameters + return type).
|
||||
|
||||
### Asset & file commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_asset`](commands/assets-and-files.md#create_asset) | Create a ScriptableObject / Object asset at a path. |
|
||||
| [`import_asset`](commands/assets-and-files.md#import_asset) | Import an external file into the project. |
|
||||
| [`move_asset`](commands/assets-and-files.md#move_asset) | Move / rename an asset (keeps its GUID). |
|
||||
| [`copy_asset`](commands/assets-and-files.md#copy_asset) | Copy an asset (fresh GUID). |
|
||||
| [`rename_asset`](commands/assets-and-files.md#rename_asset) | Rename an asset in place. |
|
||||
| [`delete_asset`](commands/assets-and-files.md#delete_asset) | Delete an asset (needs confirm). |
|
||||
| [`find_assets`](commands/assets-and-files.md#find_assets) | Find assets by type / name / label. |
|
||||
| [`set_import_settings`](commands/assets-and-files.md#set_import_settings) | Set an asset's importer settings and re-import. |
|
||||
| [`get_import_settings`](commands/assets-and-files.md#get_import_settings) | Read an asset's importer settings. |
|
||||
| [`create_folder`](commands/assets-and-files.md#create_folder) | Create a folder under the authoring root. |
|
||||
| [`read_text_file`](commands/assets-and-files.md#read_text_file) | Read a UTF-8 text file. |
|
||||
| [`write_text_file`](commands/assets-and-files.md#write_text_file) | Write a UTF-8 text file, then import it. |
|
||||
|
||||
### Scene commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_scene`](commands/scenes.md#create_scene) | Create and save a new scene. |
|
||||
| [`open_scene`](commands/scenes.md#open_scene) | Open an existing scene. |
|
||||
| [`save_scene`](commands/scenes.md#save_scene) | Save an open scene. |
|
||||
| [`save_all`](commands/scenes.md#save_all) | Save all dirty open scenes. |
|
||||
| [`list_open_scenes`](commands/scenes.md#list_open_scenes) | List open scenes and their state. |
|
||||
| [`set_active_scene`](commands/scenes.md#set_active_scene) | Set which open scene is active. |
|
||||
| [`get_scene_hierarchy`](commands/scenes.md#get_scene_hierarchy) | Return a scene's GameObject tree. |
|
||||
| [`add_scene_to_build`](commands/scenes.md#add_scene_to_build) | Add a scene to Build Settings. |
|
||||
| [`remove_scene_from_build`](commands/scenes.md#remove_scene_from_build) | Remove a scene from Build Settings. |
|
||||
|
||||
### GameObject & component commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_gameobject`](commands/gameobjects-and-components.md#create_gameobject) | Create a GameObject or primitive. |
|
||||
| [`create_gameobjects`](commands/gameobjects-and-components.md#create_gameobjects) | Batch-create GameObjects / primitives. |
|
||||
| [`find_gameobjects`](commands/gameobjects-and-components.md#find_gameobjects) | Find GameObjects by name / tag / component / path. |
|
||||
| [`set_transform`](commands/gameobjects-and-components.md#set_transform) | Set local position / rotation / scale. |
|
||||
| [`set_parent`](commands/gameobjects-and-components.md#set_parent) | Reparent a GameObject (or detach to root). |
|
||||
| [`set_active`](commands/gameobjects-and-components.md#set_active) | Set a GameObject's active state. |
|
||||
| [`set_tag`](commands/gameobjects-and-components.md#set_tag) | Set a GameObject's tag. |
|
||||
| [`set_layer`](commands/gameobjects-and-components.md#set_layer) | Set a GameObject's layer. |
|
||||
| [`rename_gameobject`](commands/gameobjects-and-components.md#rename_gameobject) | Rename a GameObject. |
|
||||
| [`delete_gameobject`](commands/gameobjects-and-components.md#delete_gameobject) | Delete a GameObject (undoable). |
|
||||
| [`add_component`](commands/gameobjects-and-components.md#add_component) | Add a component by type name. |
|
||||
| [`remove_component`](commands/gameobjects-and-components.md#remove_component) | Remove a component. |
|
||||
| [`get_component_properties`](commands/gameobjects-and-components.md#get_component_properties) | Read a component's serialized properties. |
|
||||
| [`set_component_properties`](commands/gameobjects-and-components.md#set_component_properties) | Set a component's serialized properties. |
|
||||
|
||||
### Prefab commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_prefab`](commands/prefabs.md#create_prefab) | Save a GameObject as a prefab. |
|
||||
| [`instantiate_prefab`](commands/prefabs.md#instantiate_prefab) | Instantiate a prefab into a scene. |
|
||||
| [`create_prefab_variant`](commands/prefabs.md#create_prefab_variant) | Create a prefab variant. |
|
||||
| [`apply_prefab_overrides`](commands/prefabs.md#apply_prefab_overrides) | Apply instance overrides to the source. |
|
||||
| [`revert_prefab_overrides`](commands/prefabs.md#revert_prefab_overrides) | Revert instance overrides. |
|
||||
| [`unpack_prefab`](commands/prefabs.md#unpack_prefab) | Unpack a prefab instance. |
|
||||
| [`save_prefab_contents`](commands/prefabs.md#save_prefab_contents) | Edit a prefab in an isolated stage and save. |
|
||||
|
||||
### Script commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_script`](commands/scripts.md#create_script) | Create a C# script from a template. |
|
||||
| [`attach_script`](commands/scripts.md#attach_script) | Attach a MonoBehaviour by type / asset. |
|
||||
| [`set_serialized_field`](commands/scripts.md#set_serialized_field) | Set a serialized field on a component / asset. |
|
||||
| [`get_serialized_fields`](commands/scripts.md#get_serialized_fields) | Read serialized fields. |
|
||||
|
||||
### Animation commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`create_animation_clip`](commands/animation.md#create_animation_clip) | Create an empty .anim AnimationClip. |
|
||||
| [`set_animation_curve`](commands/animation.md#set_animation_curve) | Add / replace a float curve on a clip. |
|
||||
| [`get_animation_clip`](commands/animation.md#get_animation_clip) | Read a clip's curves and metadata. |
|
||||
| [`remove_animation_curve`](commands/animation.md#remove_animation_curve) | Remove a curve binding (needs confirm). |
|
||||
| [`create_animator_controller`](commands/animation.md#create_animator_controller) | Create an .controller AnimatorController. |
|
||||
| [`add_animator_parameter`](commands/animation.md#add_animator_parameter) | Add a parameter to a controller. |
|
||||
| [`add_animator_layer`](commands/animation.md#add_animator_layer) | Add a layer to a controller. |
|
||||
| [`add_animator_state`](commands/animation.md#add_animator_state) | Add a state to a layer. |
|
||||
| [`add_animator_transition`](commands/animation.md#add_animator_transition) | Add a transition between states. |
|
||||
| [`get_animator_controller`](commands/animation.md#get_animator_controller) | Read a controller's full structure. |
|
||||
| [`create_timeline`](commands/animation.md#create_timeline) | Create a .playable Timeline asset. |
|
||||
| [`add_timeline_track`](commands/animation.md#add_timeline_track) | Add a track to a Timeline. |
|
||||
| [`add_timeline_clip`](commands/animation.md#add_timeline_clip) | Add a clip to a Timeline track. |
|
||||
| [`get_timeline`](commands/animation.md#get_timeline) | Read a Timeline's structure. |
|
||||
|
||||
### Material & shader commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`get_material_properties`](commands/materials.md#get_material_properties) | Read a material's shader and properties. |
|
||||
| [`set_material_properties`](commands/materials.md#set_material_properties) | Set material shader properties / keywords. |
|
||||
| [`list_shaders`](commands/materials.md#list_shaders) | Discover available shaders. |
|
||||
| [`get_shader_properties`](commands/materials.md#get_shader_properties) | Introspect a shader's property list. |
|
||||
|
||||
### Baking commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`bake_lighting`](commands/baking.md#bake_lighting) | Async lightmap bake (poll `lighting_bake_status`). |
|
||||
| [`lighting_bake_status`](commands/baking.md#lighting_bake_status) | Status of the last lighting bake. |
|
||||
| [`cancel_lighting_bake`](commands/baking.md#cancel_lighting_bake) | Cancel an in-progress lighting bake. |
|
||||
| [`clear_baked_lighting`](commands/baking.md#clear_baked_lighting) | Clear baked lightmaps (needs confirm). |
|
||||
| [`get_lighting_settings`](commands/baking.md#get_lighting_settings) | Read the active LightingSettings. |
|
||||
| [`set_lighting_settings`](commands/baking.md#set_lighting_settings) | Apply a subset of lighting settings. |
|
||||
| [`bake_navmesh`](commands/baking.md#bake_navmesh) | Async legacy NavMesh bake (poll `navmesh_bake_status`). |
|
||||
| [`navmesh_bake_status`](commands/baking.md#navmesh_bake_status) | Status of the last NavMesh bake. |
|
||||
| [`cancel_navmesh_bake`](commands/baking.md#cancel_navmesh_bake) | Cancel an in-progress NavMesh bake. |
|
||||
| [`clear_navmesh`](commands/baking.md#clear_navmesh) | Clear the baked NavMesh (needs confirm). |
|
||||
| [`get_navmesh_settings`](commands/baking.md#get_navmesh_settings) | Read legacy NavMesh bake settings. |
|
||||
| [`set_navmesh_settings`](commands/baking.md#set_navmesh_settings) | Apply a subset of NavMesh settings. |
|
||||
| [`bake_navmesh_surfaces`](commands/baking.md#bake_navmesh_surfaces) | Bake NavMeshSurface components (AI Navigation). |
|
||||
| [`bake_occlusion_culling`](commands/baking.md#bake_occlusion_culling) | Async occlusion bake (poll `occlusion_bake_status`). |
|
||||
| [`occlusion_bake_status`](commands/baking.md#occlusion_bake_status) | Status of the last occlusion bake. |
|
||||
| [`cancel_occlusion_bake`](commands/baking.md#cancel_occlusion_bake) | Cancel an in-progress occlusion bake. |
|
||||
| [`clear_occlusion_culling`](commands/baking.md#clear_occlusion_culling) | Clear baked occlusion data (needs confirm). |
|
||||
|
||||
### Navigation & selection commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`get_selection`](commands/navigation.md#get_selection) | Read the current Editor selection. |
|
||||
| [`set_selection`](commands/navigation.md#set_selection) | Set the Editor selection. |
|
||||
| [`search`](commands/navigation.md#search) | Run a Unity Search query. |
|
||||
|
||||
### Capture commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`capture_game_view`](commands/capture.md#capture_game_view) | Render a camera to a PNG (base64). |
|
||||
| [`capture_scene_view`](commands/capture.md#capture_scene_view) | Render the Scene View to a PNG (base64). |
|
||||
| [`capture_editor_element`](commands/capture.md#capture_editor_element) | Capture a UI Toolkit element from an EditorWindow (6000.7+). |
|
||||
| [`capture_runtime_element`](commands/capture.md#capture_runtime_element) | Capture a UI Toolkit element from a runtime panel (6000.7+). |
|
||||
|
||||
### Build, compilation & test commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`build`](commands/build-and-compilation.md#build) | Async Player build (poll `build_status`). |
|
||||
| [`build_status`](commands/build-and-compilation.md#build_status) | Status / report of the current build. |
|
||||
| [`switch_build_target`](commands/build-and-compilation.md#switch_build_target) | Switch the active build target (needs confirm). |
|
||||
| [`switch_build_target_status`](commands/build-and-compilation.md#switch_build_target_status) | Status of the last target switch. |
|
||||
| [`list_build_targets`](commands/build-and-compilation.md#list_build_targets) | List known build targets. |
|
||||
| [`get_build_settings`](commands/build-and-compilation.md#get_build_settings) | Read build configuration. |
|
||||
| [`set_build_settings`](commands/build-and-compilation.md#set_build_settings) | Set build configuration fields. |
|
||||
| [`list_build_profiles`](commands/build-and-compilation.md#list_build_profiles) | List Build Profile assets (Unity 6). |
|
||||
| [`recompile`](commands/build-and-compilation.md#recompile) | Force a script recompile (poll `recompile_status`). |
|
||||
| [`recompile_status`](commands/build-and-compilation.md#recompile_status) | Status of the last recompile. |
|
||||
| [`list_tests`](commands/build-and-compilation.md#list_tests) | List available tests without running. |
|
||||
| [`run_tests`](commands/build-and-compilation.md#run_tests) | Run Unity tests with filters. |
|
||||
| [`test_status`](commands/build-and-compilation.md#test_status) | Status of async test execution. |
|
||||
| [`cancel_tests`](commands/build-and-compilation.md#cancel_tests) | Cancel running tests. |
|
||||
|
||||
### Project settings commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`get_audio_settings`](commands/project-settings.md#get_audio_settings) | Read Audio settings. |
|
||||
| [`set_audio_settings`](commands/project-settings.md#set_audio_settings) | Change Audio settings (needs confirm). |
|
||||
| [`get_graphics_settings`](commands/project-settings.md#get_graphics_settings) | Read Graphics settings. |
|
||||
| [`set_graphics_settings`](commands/project-settings.md#set_graphics_settings) | Set the default render pipeline (needs confirm). |
|
||||
| [`get_input_settings`](commands/project-settings.md#get_input_settings) | Read legacy Input Manager axes. |
|
||||
| [`set_input_settings`](commands/project-settings.md#set_input_settings) | Tune a legacy input axis (needs confirm). |
|
||||
| [`get_physics_settings`](commands/project-settings.md#get_physics_settings) | Read Physics settings. |
|
||||
| [`set_physics_settings`](commands/project-settings.md#set_physics_settings) | Change Physics settings (needs confirm). |
|
||||
| [`get_player_settings`](commands/project-settings.md#get_player_settings) | Read PlayerSettings. |
|
||||
| [`set_player_settings`](commands/project-settings.md#set_player_settings) | Change PlayerSettings (needs confirm). |
|
||||
| [`get_quality_settings`](commands/project-settings.md#get_quality_settings) | Read QualitySettings. |
|
||||
| [`set_quality_settings`](commands/project-settings.md#set_quality_settings) | Change QualitySettings (needs confirm). |
|
||||
| [`get_tags_layers`](commands/project-settings.md#get_tags_layers) | Read tags and layers. |
|
||||
| [`set_tags_layers`](commands/project-settings.md#set_tags_layers) | Add / remove tags, name layers (needs confirm). |
|
||||
| [`get_time_settings`](commands/project-settings.md#get_time_settings) | Read Time settings. |
|
||||
| [`set_time_settings`](commands/project-settings.md#set_time_settings) | Change Time settings (needs confirm). |
|
||||
|
||||
### Package Manager commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`package_list`](commands/package-manager.md#package_list) | List packages by scope. |
|
||||
| [`package_search`](commands/package-manager.md#package_search) | Search the registry. |
|
||||
| [`package_add`](commands/package-manager.md#package_add) | Add a UPM package (needs confirm). |
|
||||
| [`package_remove`](commands/package-manager.md#package_remove) | Remove a UPM package (needs confirm). |
|
||||
| [`package_resolve`](commands/package-manager.md#package_resolve) | Resolve / refresh packages. |
|
||||
| [`package_status`](commands/package-manager.md#package_status) | Status of the last package operation. |
|
||||
|
||||
### Editor lifecycle & observability commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`editor_play`](commands/editor-lifecycle-and-observability.md#editor_play) | Enter play mode. |
|
||||
| [`editor_stop`](commands/editor-lifecycle-and-observability.md#editor_stop) | Exit play mode. |
|
||||
| [`editor_pause`](commands/editor-lifecycle-and-observability.md#editor_pause) | Pause play mode. |
|
||||
| [`editor_status`](commands/editor-lifecycle-and-observability.md#editor_status) | Detailed Editor status. |
|
||||
| [`editor_focus`](commands/editor-lifecycle-and-observability.md#editor_focus) | Bring the Editor to the foreground. |
|
||||
| [`menu`](commands/editor-lifecycle-and-observability.md#menu) | Execute (or list) Editor menu items. |
|
||||
| [`screenshot`](commands/editor-lifecycle-and-observability.md#screenshot) | Capture Scene / Game view to a PNG file. |
|
||||
| [`set_autotick`](commands/editor-lifecycle-and-observability.md#set_autotick) | Keep the editor ticking while unfocused. |
|
||||
| [`get_console_logs`](commands/editor-lifecycle-and-observability.md#get_console_logs) | Read captured Editor console logs. |
|
||||
| [`clear_console`](commands/editor-lifecycle-and-observability.md#clear_console) | Clear the console / log buffer. |
|
||||
| [`get_performance_stats`](commands/editor-lifecycle-and-observability.md#get_performance_stats) | Read render / memory / frame stats. |
|
||||
| [`get_authoring_root`](commands/editor-lifecycle-and-observability.md#get_authoring_root) | Get the authoring-root folder. |
|
||||
| [`set_authoring_root`](commands/editor-lifecycle-and-observability.md#set_authoring_root) | Set the authoring-root folder. |
|
||||
|
||||
### Runtime commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`runtime_status`](commands/runtime.md#runtime_status) | Runtime application status. |
|
||||
| [`quit`](commands/runtime.md#quit) | Quit the application. |
|
||||
| [`set_target_framerate`](commands/runtime.md#set_target_framerate) | Set the target frame rate. |
|
||||
| [`set_timescale`](commands/runtime.md#set_timescale) | Set the time scale. |
|
||||
| [`simulate_key`](commands/runtime.md#simulate_key) | Simulate a keyboard event (Input System). |
|
||||
| [`simulate_pointer`](commands/runtime.md#simulate_pointer) | Simulate a pointer event (Input System). |
|
||||
| [`log`](commands/runtime.md#log) | Write a message to the Unity console. |
|
||||
| [`console`](commands/runtime.md#console) | Read captured console output. |
|
||||
| [`eval`](commands/runtime.md#eval) | Evaluate C# via Roslyn. |
|
||||
| [`eval_file`](commands/runtime.md#eval_file) | Evaluate C# from a .cs file. |
|
||||
| [`reload_file`](commands/runtime.md#reload_file) | Apply in-place [HotReload] edits from a file. |
|
||||
| [`reload_file_override`](commands/runtime.md#reload_file_override) | Compile & apply override hot reload. |
|
||||
| [`hotreload_status`](commands/runtime.md#hotreload_status) | Hot reload registry status. |
|
||||
| [`cleanup_hotreload`](commands/runtime.md#cleanup_hotreload) | Clear old hot reload DLLs / registry. |
|
||||
@@ -0,0 +1,60 @@
|
||||
# Runtime connection & setup
|
||||
|
||||
How to run the Pipeline server inside a built Player so a client can drive it the same way it drives the Editor. The runtime server only exists in **development builds**, so setup is mostly about building correctly.
|
||||
|
||||
## The `RuntimePipelineManager` component
|
||||
|
||||
The runtime server is owned by a `RuntimePipelineManager` MonoBehaviour. Add it to a scene via the component menu:
|
||||
|
||||
> **Add Component → Pipeline → Runtime Pipeline Manager**
|
||||
|
||||
It is `[DisallowMultipleComponent]` and survives scene loads (`DontDestroyOnLoad`); only one instance should exist. Its `Update` pumps the server's dispatcher each frame (a Player has no `EditorApplication.update` to do this) and drives the listener watchdog.
|
||||
|
||||
### Inspector fields
|
||||
|
||||
| Field | Default | Meaning |
|
||||
|-------|---------|---------|
|
||||
| `enableInBuilds` | `false` | Master switch. The server only starts when this is `true`. **Off by default for safety.** |
|
||||
| `autoStart` | `true` | Start the server automatically in `Start()` (requires `enableInBuilds`). |
|
||||
| `port` | `0` | Listen port. `0` = auto-assign from `7900`–`7949`. |
|
||||
| `requestTimeoutMs` | `30000` | Per-request timeout. |
|
||||
| `enableAuditLogging` | `true` | Log remote requests for auditing. |
|
||||
| `maxWorkItemsPerFrame` | `10` | Dispatcher work items processed per frame. |
|
||||
|
||||
If `autoStart` is off you can start/stop manually with `StartServer()` / `StopServer()`.
|
||||
|
||||
## Development-build gating
|
||||
|
||||
The runtime server, code evaluation, and hot reload are all gated behind a compile-time guard:
|
||||
|
||||
```csharp
|
||||
#if UNITY_EDITOR || (UNITY_STANDALONE && DEBUG)
|
||||
```
|
||||
|
||||
`DEBUG` is defined for **standalone Development Builds** only. In a non-development (release) build the compilation/eval/hot-reload code is compiled out entirely, so it cannot run — even if `enableInBuilds` is `true`. To use the runtime server in a Player you therefore need **both**:
|
||||
|
||||
1. A **Development Build** (defines `DEBUG`), built for a **standalone** target (Windows/macOS/Linux).
|
||||
2. `enableInBuilds = true` on the `RuntimePipelineManager`.
|
||||
|
||||
## Step-by-step: enable in a dev build
|
||||
|
||||
1. Add a **Runtime Pipeline Manager** component to a GameObject in your startup scene (component menu *Pipeline → Runtime Pipeline Manager*).
|
||||
2. Tick **`enableInBuilds`** on that component. Leave `autoStart` on and `port` at `0` (auto).
|
||||
3. Open **File → Build Settings** and enable **Development Build** for a **Standalone** platform.
|
||||
4. Build and run the Player.
|
||||
5. On start, the manager creates a `RuntimePipelineServer`, which binds the first free port in `7900`–`7949` and writes the runtime descriptor `.unity-pipeline-runtime-port` (with `port` and `evalToken`).
|
||||
6. Connect a client using that port and token.
|
||||
|
||||
## Security
|
||||
|
||||
The runtime server applies the same protections as the editor server (see [Connectivity](connectivity.md)):
|
||||
|
||||
- It binds the **IPv4 loopback** (`http://127.0.0.1:<port>/`, plus the `localhost` hostname), so it is reachable only from the same machine and never exposed on a routable interface. Clients should connect to `127.0.0.1` explicitly — see [Loopback-only binding](connectivity.md#loopback-only-binding) for why `localhost` can resolve to the IPv6 loopback (`::1`), which Unity's Mono `HttpListener` cannot serve.
|
||||
- Every request must present `Authorization: Bearer <evalToken>`; the token is generated at startup and published in the runtime descriptor.
|
||||
|
||||
Because the server exposes code evaluation and hot reload, only enable it in development/QA builds — never in a production build without additional safeguards.
|
||||
|
||||
## See also
|
||||
|
||||
- [Connectivity](connectivity.md) — ports, descriptor file, and auth in detail.
|
||||
- [Hot reload](hot-reload.md) — applying live code changes to a running Player.
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
# Safety & mutations
|
||||
|
||||
Mutating commands — asset writes, project-settings changes, package/build changes —
|
||||
share two conventions so command authors and clients know what to expect: a `confirm`/`dry_run` gate
|
||||
on destructive or overwriting operations, and Undo grouping via `AuthoringUndoScope`. Commands that
|
||||
resolve caller-supplied asset paths confine them with `ProjectPaths` (see
|
||||
[Creating authoring commands](authoring-commands.md)). The helpers live in `Editor/Authoring/`.
|
||||
|
||||
### The confirm / dry_run convention
|
||||
|
||||
Destructive or overwriting commands expose two boolean `[CliArg]`s — `confirm` and `dry_run` — and
|
||||
gate their own mutation on them. There is no central dispatcher; each command applies the same simple
|
||||
rules inline:
|
||||
|
||||
- **`dry_run == true`** → validate and describe the intended change, mutate nothing, return a preview.
|
||||
This wins even if `confirm` is also true.
|
||||
- **`confirm == false`** (and not a dry run) → refuse without mutating. Return the failure the way the
|
||||
command reports its other errors — `throw new ArgumentException(...)` for the throwing style (e.g.
|
||||
`delete_asset`, `clear_baked_lighting`), or a structured error object for commands that return
|
||||
structured results (e.g. `build`, which returns `{ success = false, status = "error", message = "…" }`).
|
||||
- **otherwise** (`confirm == true`, not a dry run) → perform the mutation. Group *scene/object*
|
||||
mutations in an `AuthoringUndoScope` (see below). Asset/settings/package writes are **not** part of
|
||||
Unity's Undo, so they run directly — say so in the command description ("Not undoable via Ctrl+Z.").
|
||||
|
||||
```csharp
|
||||
[CliCommand("clear_baked_lighting", "Clear baked lightmap data for the open scene(s). Destructive: requires confirm=true (use dry_run to preview). Not undoable via Ctrl+Z.")]
|
||||
public static object ClearBakedLighting(
|
||||
[CliArg("confirm", "Apply the clear. Without it the call is refused.")] bool confirm = false,
|
||||
[CliArg("dry_run", "Preview what would be cleared without clearing it.")] bool dryRun = false)
|
||||
{
|
||||
// …resolve the open scene(s)…
|
||||
if (dryRun)
|
||||
return new { status = "dry_run", wouldClear = true };
|
||||
if (!confirm)
|
||||
throw new ArgumentException("Refusing to clear baked lighting. Pass confirm=true to apply, or dry_run=true to preview.");
|
||||
|
||||
// Clearing baked GI is not part of Unity's Undo — no AuthoringUndoScope.
|
||||
Lightmapping.Clear();
|
||||
|
||||
return new { cleared = true };
|
||||
}
|
||||
```
|
||||
|
||||
Purely additive, non-destructive commands (e.g. `create_folder`, `add_animator_parameter`)
|
||||
do not take `confirm`/`dry_run`; they just perform the mutation directly.
|
||||
|
||||
### Undo grouping
|
||||
|
||||
Scene/object mutations are grouped with `AuthoringUndoScope` so a multi-step command reverts as a
|
||||
single Ctrl+Z step. It increments Unity's current Undo group on construction and calls
|
||||
`Undo.CollapseUndoOperations` on dispose, collapsing everything the body registers — via
|
||||
`Undo.RecordObject`, `Undo.RegisterCreatedObjectUndo`, and similar — into one named step. The command
|
||||
opts into Undo by calling those APIs inside the scope. See
|
||||
[Creating authoring commands](authoring-commands.md) for the full pattern and the per-mutation `Undo`
|
||||
API table.
|
||||
|
||||
> **Caveat.** Some operations are not part of Unity's Undo system. `AssetDatabase` operations, UPM
|
||||
> package changes, and settings backed by native assets may not be undoable; for those the collapse is
|
||||
> simply a no-op and Ctrl+Z will not revert the change. Don't rely on Undo to clean up such writes —
|
||||
> validate up front and fail before writing.
|
||||
|
||||
### Path confinement
|
||||
|
||||
Commands that accept a caller-supplied asset path resolve it through `ProjectPaths.Resolve`, which
|
||||
normalizes the path, rejects `..` traversal, and confines it to the configurable authoring root
|
||||
(default `Assets`) so agent-supplied paths cannot escape the project. It returns a project-relative
|
||||
path, or `null` with an `error` string when the path escapes the root.
|
||||
|
||||
```csharp
|
||||
var normalized = ProjectPaths.Resolve(path, out var error);
|
||||
if (normalized == null)
|
||||
throw new ArgumentException(error);
|
||||
// normalized is project-relative and guaranteed to live under the authoring root.
|
||||
```
|
||||
|
||||
See [Creating authoring commands](authoring-commands.md) for the full path-handling rules and the
|
||||
`set_authoring_root` / `get_authoring_root` commands that adjust the root.
|
||||
|
||||
### For command authors
|
||||
|
||||
To make a mutating command safe:
|
||||
|
||||
1. If the operation is destructive or overwrites existing content, add `confirm` and `dry_run` boolean
|
||||
`[CliArg]`s and gate on them inline (preview on `dry_run`, refuse on `!confirm`).
|
||||
2. Group scene/object mutations in `using (new AuthoringUndoScope("<operation>"))` and register Undo
|
||||
operations inside it where the mutation is undoable.
|
||||
3. Resolve any caller-supplied asset path through `ProjectPaths.Resolve` before touching the filesystem
|
||||
— ideally during validation, so a bad path fails before anything is applied.
|
||||
|
||||
See [Creating commands](creating-commands.md) and [Creating authoring commands](authoring-commands.md).
|
||||
@@ -0,0 +1,95 @@
|
||||
# Tests architecture
|
||||
|
||||
How the package's tests exercise commands. There are two complementary styles — **ViaClient** (over real HTTP, end-to-end) and **CommandDirect** (calling the static command method straight) — backed by a small set of shared test helpers.
|
||||
|
||||
## Two test styles
|
||||
|
||||
### ViaClient — exercise the full HTTP path
|
||||
|
||||
Spin up an isolated `PipelineTestServer` and call `server.Execute(command, params)`. This goes over HTTP through the same routing, parameter coercion, and threading the real server uses — it tests the command *as a client sees it*.
|
||||
|
||||
```csharp
|
||||
[Test]
|
||||
public void SetTransform_ViaClient_ArrayParams_Apply()
|
||||
{
|
||||
var go = Track(new GameObject("Xform219_Arrays"));
|
||||
|
||||
using (var server = new PipelineTestServer())
|
||||
{
|
||||
var response = server.Execute("set_transform", new
|
||||
{
|
||||
target = new { instanceId = PipelineUtils.GetObjectId(go) },
|
||||
position = new[] { 1f, 2f, 3f },
|
||||
rotation = new[] { 0f, 90f, 0f },
|
||||
scale = new[] { 2f, 2f, 2f }
|
||||
});
|
||||
|
||||
Assert.IsTrue(response.IsSuccess, $"set_transform should succeed: {response.Error}");
|
||||
Assert.AreEqual(new Vector3(1, 2, 3), go.transform.localPosition);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The test server is isolated: it uses the **test editor port range `7850`–`7899`** and **writes no descriptor**, so it never disturbs the live editor server (which uses `7800`–`7849`). `Execute` pumps the server's own dispatcher while the HTTP call is in flight, so `MainThreadRequired` commands complete even from a plain `[Test]` that blocks the main thread — no deadlock.
|
||||
|
||||
### CommandDirect — call the static method directly
|
||||
|
||||
Call the command's static method with typed arguments. This is synchronous, with **no server, HTTP, or dispatcher** involved — fast and ideal for unit-testing command logic and parameter handling.
|
||||
|
||||
```csharp
|
||||
[Test]
|
||||
public void SetTransform_Direct_TypedArrays_Apply()
|
||||
{
|
||||
var go = Track(new GameObject("Xform219_Direct"));
|
||||
|
||||
GameObjectCommands.SetTransform(RefTo(go),
|
||||
position: new[] { 1f, 2f, 3f },
|
||||
rotation: new[] { 0f, 90f, 0f },
|
||||
scale: new[] { 2f, 2f, 2f });
|
||||
|
||||
Assert.AreEqual(new Vector3(1, 2, 3), go.transform.localPosition);
|
||||
Assert.AreEqual(new Vector3(2, 2, 2), go.transform.localScale);
|
||||
}
|
||||
```
|
||||
|
||||
Use **CommandDirect** to verify a command's behavior with strongly-typed inputs; use **ViaClient** to additionally verify wire-level concerns (JSON coercion, required-parameter validation, threading).
|
||||
|
||||
## Shared helpers
|
||||
|
||||
| Helper | Role |
|
||||
|--------|------|
|
||||
| `PipelineTestServer` | Disposable wrapper that starts an isolated `TestEditorPipelineServer`, wires up a `PipelineClient`, and exposes `Execute(command, parameters, timeoutMs = 30000)`. Pumps the server dispatcher during each call to avoid main-thread deadlock. |
|
||||
| `TestEditorPipelineServer` | `EditorPipelineServer` subclass for tests. Overrides `WritesDescriptor => false`, `GetPortRange() => (7850, 7899)`, and `GetToken()` (from `SecurityTokenManager`) so it is fully isolated from the live server. |
|
||||
| `PipelineClient` | Test-side HTTP client. Constructed from a URL+token or a server/manager instance. Key methods: `ExecuteCommandAsync` (`/api/exec`), `GetStatusAsync` (`/api/status`), `PostJsonAsync`. Returns a `PipelineResponse` (`IsSuccess`, `StatusCode`, `Error`, `JsonResponse`, `IsCommandSuccess`). |
|
||||
| `EditorTestUtilities` | Async helpers for editor state, e.g. `WaitFor(Func<bool> condition, timeoutMs)` to poll a condition without busy-waiting. |
|
||||
| `LiveServerGuard` | Assembly-level `ITestAction` that asserts the **live editor server survives the test run**. |
|
||||
|
||||
### `PipelineTestServer` setup
|
||||
|
||||
```csharp
|
||||
public PipelineTestServer()
|
||||
{
|
||||
m_Server = new TestEditorPipelineServer();
|
||||
m_Server.Start(); // auto-assigns a port in 7850-7899; writes no descriptor
|
||||
m_Client = new PipelineClient($"http://localhost:{m_Server.Port}", SecurityTokenManager.GetOrCreateToken());
|
||||
}
|
||||
```
|
||||
|
||||
Wrap it in a `using` (it is disposable) so the isolated server is stopped at the end of the test.
|
||||
|
||||
### `LiveServerGuard`
|
||||
|
||||
Applied once at assembly scope (`[assembly: LiveServerGuard]`), it runs before and after **every** test in the editor suite. If a live editor server was advertising its descriptor before a test, the guard asserts afterwards that the test did not disturb it — the descriptor still exists, the port is unchanged, and the server is still listening:
|
||||
|
||||
```csharp
|
||||
Assert.IsNotNull(after, $"'{test.Name}' deleted the live pipeline server descriptor");
|
||||
Assert.AreEqual(m_Before.Port, after.Port, $"'{test.Name}' changed the port");
|
||||
Assert.IsTrue(IsListening(after.Port, after.EvalToken), $"'{test.Name}' left the server not responding");
|
||||
```
|
||||
|
||||
This is what makes it safe to "dogfood" — run the test suite against the very editor you are driving — without a test clobbering the live server. Tests that intentionally start/stop the live server are marked `[Explicit]` and must hand it back intact.
|
||||
|
||||
## See also
|
||||
|
||||
- [Creating commands](creating-commands.md) — the command API these tests exercise.
|
||||
- [Connectivity](connectivity.md) — ports, descriptor, and auth (the test server deliberately skips the descriptor).
|
||||
Reference in New Issue
Block a user