Skip to content

Authoring API ​

Namespace GodotECS.Authoring. Editor-side nodes that describe entities, the baker that converts them to EntityScene, and runtime spawning helpers. See Authoring workflow for the big picture.

Baker ​

csharp
public static class Baker
{
    public static EntityScene BakeSubtree(Node root);
    public static int BakeSubtreeInto(World world, Node root);
}
  • BakeSubtree(Node root) — bakes the subtree into a throwaway World and returns EntityScene.FromWorld(tmp). Throws ArgumentNullException on null root. Cold path; allocations allowed.
  • BakeSubtreeInto(World world, Node root) — bakes into an existing world (e.g. World.Preview), returns the number of entities created. Throws ArgumentNullException on null world or root.
  • Traversal is pre-order (parent before children) so Parent references resolve. Only EcsAuthoring3D / EcsAuthoring2D nodes emit entities; other nodes are transparent containers. Dispatch is by is checks — no runtime reflection.

EcsAuthoring3D ​

csharp
public partial class EcsAuthoring3D : Node3D
{
    [Export] public Mesh Mesh;
    [Export] public Material MaterialOverride;
    [Export] public bool IsStatic;
    [Export] public float Radius = 0.5f;
    [Export] public int Health = 100;
    [Export] public int MaxHealth = 100;
    [Export] public Godot.Vector3 Velocity;
    [Export] public Godot.Color Tint = Colors.White;

    public EntityScene Baked { get; private set; }
    public Entity Bake(World world);
    public EntityScene BakeScene();
    internal static Entity BakeInto(World world, EcsAuthoring3D node, Entity parent);
}
  • Bake(World world) — bakes this node (no children) into world as a root entity (parent = Entity.Null). Throws ArgumentNullException on null world.
  • BakeScene() — bakes into a throwaway world, caches the result on Baked, returns it.
  • BakeInto(World, EcsAuthoring3D, Entity) — core routine used by Baker: creates the entity and writes LocalTransform (from StaticBake.WorldTransformOf(node): GlobalTransform inside the tree, the composed local chain when outside, so tooling can bake before instancing; rotation from basis.GetRotationQuaternion() with identity fallback, uniform scale = basis-scale average, 1 when non-positive), Velocity, Health (Max raised to Value if lower), PhysicsStaticTag + PhysicsRadius when IsStatic else PhysicsVelocity + PhysicsRadius (radius clamped to 0.5 when ≤ 0.01), PhysicsLayer.Default, shared RenderMeshRef { GroupId = 0 } (resolved later at sync), RenderColor, and Parent when parent is not null.

EcsAuthoring2D ​

csharp
public partial class EcsAuthoring2D : Node2D
{
    [Export] public Texture2D Texture;
    [Export] public Godot.Vector2 Size = new Godot.Vector2(16.0f, 16.0f);
    [Export] public Godot.Color Modulate = Colors.White;
    [Export] public int Health = 100;
    [Export] public Godot.Vector2 Velocity2D;

    public EntityScene Baked { get; private set; }
    public Entity Bake(World world);
    public EntityScene BakeScene();
    internal static Entity BakeInto(World world, EcsAuthoring2D node, Entity parent);
}
  • Bake(World world) / BakeScene() / Baked — same contract as the 3D variant. Modulate is declared public new (it intentionally shadows CanvasItem.Modulate so the exported field feeds RenderColor).
  • BakeInto(World, EcsAuthoring2D, Entity) — writes LocalTransform (GlobalPosition → Vector3(x, y, 0), Z-axis quaternion from GlobalRotation, averaged GlobalScale — or the local Position/Rotation/Scale when the node is outside the tree), Velocity (from Velocity2D), Health (Max = Value), shared SpriteRef { AtlasGroupId = 0 } (resolved later at sync), SpriteSize, RenderColor, and Parent when applicable.

EntitySceneInstance ​

csharp
public partial class EntitySceneInstance : Node
{
    [Export] public EntityScene Scene;
    [Export] public int Count = 1;
    [Export] public float SpawnRadius = 5.0f;
    [Export] public float StreamDistance = 100.0f;

    public Entity Spawn(World world, Godot.Vector3 pos);
    public Entity SpawnDefault(Godot.Vector3 pos);
    public Entity[] SpawnAll(World world, Godot.Vector3 origin);
    public Entity[] SpawnAll(World world, Godot.Vector3 origin, Godot.Vector3 streamOrigin);
}
  • Spawn(World world, Vector3 pos) — instantiates Scene once at pos via Scene.Instantiate(world, pos). Returns Entity.Null for null world (throws ArgumentNullException), null scene, or empty Data.
  • SpawnDefault(Vector3 pos) — Spawn(World.Default, pos).
  • SpawnAll(World world, Vector3 origin) — instantiates Count copies (negative → 0) scattered on a ring around origin.
  • SpawnAll(World world, Vector3 origin, Vector3 streamOrigin) — explicit streaming origin for headless/tests.
  • Streaming gate: when StreamDistance > 0 and the stream origin is farther than StreamDistance, nothing spawns and an all-Entity.Null array is returned. The 2-argument overload resolves the stream origin from the current camera (GetViewport().GetCamera3D().GlobalPosition, Vector3.Zero outside the tree), so distance streaming follows the player — origin is only the placement center. When spawning, copy i is placed at origin plus ring offset (cos(a) * SpawnRadius, 0, sin(a) * SpawnRadius) with a = (i / n) * TAU (no offset when n == 1 or SpawnRadius <= 0).

StaticBake ​

csharp
public static class StaticBake
{
    public static StaticCollider[] BakeFromStatics(Node root);
}

Walks the subtree and returns world-space static colliders (GodotECS.Physics.StaticCollider { Kind, Center, HalfExtents, Radius, Height, Layer }). Returns an empty array for null root. Sources: CollisionShape3D under a StaticBody3D (BoxShape3D → Box, SphereShape3D → Sphere, CapsuleShape3D → Capsule; skips disabled shapes, shapes without a StaticBody3D ancestor, and shapes flagged with _baked_disabled meta; copies the body's CollisionLayer), GridMap used cells (one Box per cell, world-transformed via MapToLocal), and TileMap layer-0 used cells (flat Box; layer taken from the TileSet's physics layer when present, else 1; skipped without a TileSet or layers).

Bake works on rotated/scaled content and outside the tree:

  • All world transforms go through WorldTransformOf / WorldTransform2DOf (GlobalTransform inside the tree, composed local chain outside), so baking before instancing is safe.
  • Rotated boxes/grid cells produce conservative world AABBs (AbsBasisHalf: |basis| columns applied to the local half extents) instead of the old under-estimated half × |scale|.
  • TileMap flip H/V mirrors around the cell center (no center shift) and transpose swaps the half-extent axes when the tile is not square.

GodotECS docs — version 0.2.0. All rights reserved until a license is added.