6.4 KiB
Bevy Remote Protocol (BRP)
The editor enables Bevy’s built-in Remote Plugin over HTTP for automation, CI, and future tooling interop. BRP is editor-only — the shipped game binary does not expose a port.
Enablement
BrpPlugin in crates/editor/src/ext/brp.rs adds:
RemotePlugin— core remote APIRemoteHttpPlugin— HTTP transport
Launch the editor with dev features as usual:
cargo run -p editor --features dev
Default HTTP endpoint follows Bevy 0.19 remote defaults (port 15702, routes under /remote/).
Authoring-only mutation policy
BRP and durable automation must mutate authoring components only — the same allowlist used on
scene save in scene_io.rs. Hydration rebuilds runtime ECS (Mesh3d, Bevy lights, physics,
WorldAssetRoot, etc.) on the next frame. One deliberate editor-only exception exists for
MaterialPropertyBlocks: trusted local tooling may inject this explicitly runtime-only component
to preview or promote a transient override. It is still excluded from scene/prefab persistence and
the Add Component registry.
| Allowed (examples) | Forbidden on level objects |
|---|---|
Transform, Name, ActorKind |
PointLight, SpotLight, DirectionalLight |
Primitive, StaticMeshRenderer, SkinnedMeshRenderer, brush-only legacy MaterialDesc, LightDesc |
Mesh3d, MeshMaterial3d, RigidBody, Collider |
ModelRef, RigidBodyDesc, ColliderDesc, legacy PhysicsBody, gameplay markers |
WorldAssetRoot, generated static/skinned roots, internal visibility types |
PostProcessVolumeDesc |
Runtime post-process components on cameras |
shared::renderer_material::MaterialPropertyBlocks is a runtime diagnostic/tooling exception, not
a durable authoring component. Use Promote to Material Instance in the exact Inspector slot when
the variation should become project content.
Prefer:
- Editing
LightDescinstead ofSpotLight/DirectionalLight - Editing the owning
Primitive.surfaceor rendererMaterialSlotSetinstead ofStandardMaterialhandles;MaterialDescis limited to the brush/legacy fallback path - Editing
StaticMeshRendererinstead of childMesh3dentities - Editing
SkinnedMeshRendererinstead of its hydrated joint/mesh hierarchy - Editing
ColliderDesc/RigidBodyDescinstead of runtime Avian components - Version-controlled
assets/levels/*.scn.ronfor durable changes
See ADR 0009 — Authoring vs hydrated.
Example flows
List entities
curl -s http://127.0.0.1:15702/remote/world/entities | head
Get entity components
curl -s -X POST http://127.0.0.1:15702/remote/world/get \
-H 'Content-Type: application/json' \
-d '{"entity":4294967296,"components":["bevy_transform::Transform"]}'
Mutate authoring transform (automation smoke)
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
-H 'Content-Type: application/json' \
-d '{"entity":4294967296,"component":"bevy_transform::Transform","value":{"translation":[0,2,0]}}'
Replace entity with a live id from the list call while the editor is running.
Mutate LightDesc (not runtime lights)
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
-H 'Content-Type: application/json' \
-d '{"entity":ENTITY_ID,"component":"shared::components::LightDesc","value":{...}}'
Hydration applies the change to viewport lighting after the next update.
Mutate PostProcessVolumeDesc
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
-H 'Content-Type: application/json' \
-d '{"entity":ENTITY_ID,"component":"shared::components::PostProcessVolumeDesc","value":{...}}'
Overrides use None = inherit project; Some(v) = local override per field.
Editor command palette bridge
Registered commands in extensibility.rs are invokable via Ctrl+P and PendingEditorCommands:
| Command | Action |
|---|---|
play.toggle |
Edit / Play |
play.toggle_pause |
Pause / resume sim in Play |
play.toggle_possession |
Possess / eject (Play only) |
scene.reset_lighting |
Remove all authored LightDesc; use project sun/ambient |
selection.group |
Spawn empty group; reparent selection |
selection.focus |
Frame editor camera on selection (same as F) |
rendering.create_volume |
Spawn post-process volume at editor camera |
rendering.select_volumes_at_camera |
Select highest-priority volume at camera |
rendering.focus_active_volumes |
Select + frame volumes at camera |
External automation can enqueue the same names through the editor command queue when integrated.
CI / headless validation
Validate committed levels and prefab dependency graphs without the editor UI:
cargo validate-levels
# JSON for CI, packaging, or external tools
cargo validate-levels --json
This runs the shared scene::validate_project report used by the editor Diagnostics window. It
validates authored levels and recursive prefab/composition graphs, emits an owner-attributed
dependency manifest, reports blocking content references, and exits nonzero on errors.
--project <path> validates another project root. The graph pass validates link paths, stable actor
identity, cycles, anchors, and override payloads without starting the editor. The same report scans
project settings and asset roots, registry/import dependencies, generated mesh manifests, material
and shader documents, post effects, brush geometry, collider dimensions, Git LFS hydration, and
platform requirements. Validation and packaging share one runtime-inclusion policy: hidden/editor
trees, source formats such as PSD/Blend, symlinks, and unreadable traversal are blocking when a
runtime dependency reaches them. asset.git_lfs_object_missing is blocking; run git lfs pull in
the project checkout and rerun validation before building a package.
cargo test -p shared
cargo test -p scene
cargo check -p editor --features dev
Safety
- Run BRP only in trusted local dev environments.
- Do not enable
BrpPluginin production game builds. - Scene files remain the source of truth; prefer version-controlled
assets/levels/*.scn.ronover live mutation for durable changes.