Bridge API
Namespace GodotECS.Bridge. Components for talking to Godot, plus the main-thread bridge nodes that drain them at sync points. See Godot bridge for the usage model.
Components
AudioEvent
public struct AudioEvent : IBufferElementData
{
public int BankId;
public Godot.Vector3 Pos;
public float Volume;
}One positional sound request. Lives in a buffer on the emitting entity; drained by AudioBridge.Flush(). BankId selects a stream registered via RegisterBank, Pos is the world-space emission point, Volume is linear gain (0–1).
NetworkId
public struct NetworkId : IComponentData
{
public int Id;
}Network identity for replication / remote spawning. Plain tag-along id; no system in the bridge reads it — your netcode does.
NavPath
public struct NavPath : IBufferElementData
{
public Godot.Vector3 Point;
}One waypoint of a resolved path. The buffer is cleared and rewritten by NavBridge.ProcessBudget on success.
NavRequest
public struct NavRequest : IComponentData
{
public Godot.Vector3 Target;
public int RequestId;
public bool Pending;
}Path request. Set Pending = true to enqueue; NavBridge sets it to false once the NavPath buffer holds the result. Failed queries (query returns false) leave it Pending for a later frame.
BridgeClock
public struct BridgeClock : ISingleton
{
public uint Tick;
}World-tick mirror for Godot-side readers. Singleton; Tick mirrors World.Tick.
Audio
IAudioSink
public interface IAudioSink
{
void Play(int bankId, Godot.Vector3 pos, float volume);
int Played { get; }
}Mockable playback target. The engine implementation drives real players; tests inject a counting mock. Played is the total number of Play calls received.
NullAudioSink
public sealed class NullAudioSink : IAudioSink
{
public int Played { get; private set; }
public void Play(int bankId, Godot.Vector3 pos, float volume);
}Counts plays, plays nothing. Play ignores its arguments except incrementing Played. Default test double for AudioBridge.Sink.
AudioBridge
public partial class AudioBridge : Godot.Node
{
public const int MaxVoices = 32;
public IAudioSink Sink { get; set; }
public int PendingCount { get; }
public void RegisterBank(int bankId, Godot.AudioStream stream);
public void PushBank(int bankId, Godot.Vector3 pos, float volume);
public static List<AudioEvent> ClusterCap(List<AudioEvent> src, int cap);
public int Flush();
public override void _Ready();
public override void _Process(double delta);
}MaxVoices— voice pool size and per-flush cap.Sink— when null,Flushonly drives the real player pool; set a mock in tests.PendingCount— queued events not yet flushed.RegisterBank— maps a bank id to a stream (overwrites existing).PushBank— appends oneAudioEventto the pending queue.ClusterCap— returns a copy ofsrcsorted by descendingVolume, truncated tocap. Does not modifysrc.Flush()— plays at mostMaxVoicespending events (loudest first), clears the queue, returns the number played. Each event goes toSink?.Play(...)and to a round-robinAudioStreamPlayer3Dfrom the pool — but only if its bank is registered and non-null. Volume is clamped to[0.0001, 1]and converted withLinearToDb. Returns0when the queue is empty._Ready()— creates the 32AudioStreamPlayer3Dchildren (Voice0…Voice31)._Process(double delta)— flushes automatically when the queue is non-empty.
Signals
EcsSignals
public partial class EcsSignals : Godot.Node
{
[Godot.Signal]
public delegate void EntityDiedEventHandler(int index, int version);
[Godot.Signal]
public delegate void HitPlayerEventHandler(int damage);
public readonly List<Entity> EmittedDeaths;
public readonly List<int> EmittedHits;
public int PendingDeaths { get; }
public int PendingHits { get; }
public void EnqueueDeath(Entity e);
public void EnqueueHit(int damage);
public int EmitPending();
public override void _Process(double delta);
}- Signals:
EntityDied(index, version)per dead entity,HitPlayer(damage)per hit. EnqueueDeath— queues unlesse.IsNull.EnqueueHit— always queues.EmitPending()— drains deaths first, then hits; appends toEmittedDeaths/EmittedHits, emits the Godot signals, returns the total emitted._Process(double delta)— callsEmitPending()when either queue is non-empty.
Navigation
INavQuery
public interface INavQuery
{
bool TryGetPath(Godot.Vector3 from, Godot.Vector3 to, List<Godot.Vector3> outPoints);
}Mockable path query. Fills outPoints; returns false when no path exists (the request stays Pending).
StraightLineQuery
public sealed class StraightLineQuery : INavQuery
{
public bool TryGetPath(Godot.Vector3 from, Godot.Vector3 to, List<Godot.Vector3> outPoints);
}Server-free default: appends from then to, always returns true.
NavBridge
public partial class NavBridge : Godot.Node
{
public const int PathsPerFrame = 64;
public INavQuery Query { get; set; }
public int Budget { get; set; }
public static int ProcessBudget(World world, INavQuery query, int budget);
public override void _PhysicsProcess(double delta);
}PathsPerFrame— default per-frame budget (64).Budget— current budget, initialized toPathsPerFrame; set to0/negative to pause resolution (ProcessBudgetreturns0).ProcessBudget(World world, INavQuery query, int budget)— resolves up tobudgetPendingNavRequests: start isLocalTransform.Pos(orVector3.Zero), on success theNavPathbuffer is cleared and refilled andPendingset tofalse. Returns the resolved count. Returns0for null world/query, non-positive budget, or empty world. Entities whose query call returnsfalseare skipped without consuming budget._PhysicsProcess(double delta)—ProcessBudget(World.Default, Query ?? StraightLineQuery, Budget).
GDScript facade
GdScriptApi
public partial class GdScriptApi : Godot.Node
{
public int GetEntityCount();
public uint GetTick();
public int SpawnScene(EntityScene scene, Godot.Vector3 pos);
public bool KillEntity(int index, int version);
public Godot.Vector3 GetEntityPos(int index, int version);
}All methods operate on World.Default:
GetEntityCount()—Entities.LiveCount.GetTick()—World.Tick.SpawnScene(EntityScene scene, Vector3 pos)— appends the scene atpos; returns the root entity'sIndex, or-1for a null/empty scene.KillEntity(int index, int version)— destroys the entity;falseif not alive.GetEntityPos(int index, int version)—LocalTransform.Pos, orVector3.Zerowhen dead or lacking the component.