Skip to content

Behavior Class

Definition

Namespace: Brine2D.ECS

Base class for behaviors, which contain logic that operates on a single entity. Each entity gets its own behavior instance with constructor injection support.

C#
public abstract class Behavior

Inheritance System.Object → Behavior

Remarks

Use behaviors for entity-specific logic (player movement, boss AI, etc.). For batch processing of many entities, use systems instead.

Ambient vs. parameter-passed:Behavior exposes its framework services (Entity, Input, Renderer, Logger, Audio, Game) as ambient properties, the same convention Scene/SceneBase use, because exactly one behavior instance is bound to exactly one entity for its entire attached lifetime, so the context never changes between OnAdded(), Update\(GameTime\), FixedUpdate\(GameTime\), Render\(IRenderer, GameTime\), and any other lifecycle callback, so there is no need to re-supply it on every call. Systems (IUpdateSystem, IFixedUpdateSystem, IRenderSystem) are the opposite shape: a single system instance batch-processes many entities per call, so there is no single "current entity" to be ambient about. Those APIs instead take the IEntityWorld (and entities/components within it) as explicit parameters. Prefer ambient properties for anything scoped to "this behavior's entity, for as long as it's attached"; prefer parameters for anything that varies per call or per entity within a single call.

Execution order: During Brine2D.ECS.EntityWorld.Update\(Brine2D\.Core\.GameTime\), all IUpdateSystems run first (sorted by UpdateOrder), then all behaviors (sorted by UpdateOrder). During Brine2D.ECS.EntityWorld.FixedUpdate\(Brine2D\.Core\.GameTime\), all IFixedUpdateSystems run first (sorted by FixedUpdateOrder), then all behaviors (sorted by FixedUpdateOrder). During Brine2D.ECS.EntityWorld.Render\(Brine2D\.Rendering\.IRenderer,Brine2D\.Core\.GameTime\), all IRenderSystems run first (sorted by RenderOrder), then all behaviors (sorted by RenderOrder). Behaviors therefore always execute after system-rendered content. If you need to render between systems, move the render logic into a custom IRenderSystem with the appropriate RenderOrder.

C#
public class PlayerMovementBehavior : Behavior
{
    public override int UpdateOrder => 10;

    public override void Update(GameTime gameTime)
    {
        if (Input.IsKeyDown(Key.W))
            Audio.PlaySound(_footstep);
    }
}
Fields
_started Tracks whether OnStart() has been called for this instance.
_startFailed Tracks whether OnStart() threw an exception. When true, all future Update/FixedUpdate/Render ticks are skipped so uninitialized state is never processed.
Properties
Audio Audio player for this behavior's scene. Available from OnAdded() onwards.
Entity The entity this behavior is attached to.
EntityOrNull Non-throwing internal read of the current entity reference, used only by EntityWorld's per-frame dispatch loops to check whether a behavior is still attached without incurring exception overhead. Brine2D.ECS.Entity.#ctor can be nulled out synchronously \(via [RemoveBehavior<T>\(\)](../Entity/RemoveBehavior_T_().md 'Brine2D.ECS.Entity.RemoveBehavior\<T>()') or Destroy()) even though removal from EntityWorld's dispatch lists is deferred until the next pass, so this must reflect the immediate value.
FixedUpdateOrder Controls execution order relative to other behaviors during FixedUpdate. Lower values run first. Default is 0. Behaviors with the same order run in the order they were added.
Game Game context for this behavior's scene. Available from OnAdded() onwards.
Input Input context for this behavior's scene. Available from OnAdded() onwards.
IsEnabled Whether this behavior is enabled \(affects Update, FixedUpdate, and Render calls\).
Logger Logger for this behavior. Available from OnAdded() onwards.
Renderer Renderer for this behavior's scene. Available from OnAdded() onwards.
RenderOrder Controls execution order relative to other behaviors during Render. Lower values run first. Default is 0. Behaviors with the same order run in the order they were added.
StartFailed Gets whether OnStart() threw an exception on its last attempt. When true, the behavior is silently skipped each tick. Call ResetStart() to allow OnStart() to run again.
UpdateOrder Controls execution order relative to other behaviors during Update. Lower values run first. Default is 0. Behaviors with the same order run in the order they were added.
Methods
FixedUpdate\(GameTime\) Called at a fixed timestep if enabled. Use this for deterministic simulation logic \(physics responses, AI ticks, etc\.\).
OnAdded() Called once when the behavior is added to an entity. Use this to validate required components and cache references.
OnComponentAdded\(Component\) Called when a component is added to the same entity as this behavior. Fires after the component's own OnAdded() has run.
OnComponentRemoved\(Component\) Called when a component is removed from the same entity as this behavior. Fires before the component's Entity reference is cleared, so the component is still accessible via Brine2D.ECS.Entity.GetComponent<> during this callback.
OnDestroyed() Called when the owning entity is destroyed \(via [Destroy\(\)](../Entity/Destroy().md 'Brine2D.ECS.Entity.Destroy()') or DestroyEntity\(Entity\)). Fires before OnRemoved() and while Entity is still set, so sibling components and behaviors are still accessible. Use this to distinguish entity destruction from a hot-swap removal triggered by RemoveBehavior<T>(), which calls only OnRemoved().
OnDisabled() Called when this behavior transitions from enabled to disabled \(i\.e\., [IsEnabled](IsEnabled.md 'Brine2D\.ECS\.Behavior\.IsEnabled') changes to [false](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/builtin\-types/bool')\). Also called when the owning entity transitions from active to inactive \([IsActive](../Entity/IsActive.md 'Brine2D\.ECS\.Entity\.IsActive') changes to [false](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/builtin\-types/bool')\) and this behavior's IsEnabled is already true. Override to pause state, stop effects, or clear accumulators.
OnEnabled() Called when this behavior transitions from disabled to enabled \(i\.e\., [IsEnabled](IsEnabled.md 'Brine2D\.ECS\.Behavior\.IsEnabled') changes to [true](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/builtin\-types/bool')\). Also called when the owning entity transitions from inactive to active \([IsActive](../Entity/IsActive.md 'Brine2D\.ECS\.Entity\.IsActive') changes to [true](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool 'https://docs\.microsoft\.com/en\-us/dotnet/csharp/language\-reference/builtin\-types/bool')\) and this behavior's IsEnabled is already true. Override to resume state or restart effects.
OnRemoved() Called when the behavior is removed from an entity.
OnStart() Called once before the first tick of this behavior's lifecycle, guaranteed to run before the first Update\(GameTime\), FixedUpdate\(GameTime\), or Render\(IRenderer, GameTime\) call, whichever occurs first. Use this to perform initialization that depends on all entities and components being present, e.g., looking up sibling entities or caching cross-entity references.
Render\(IRenderer, GameTime\) Called every frame during the render pass if enabled. Runs \<b>after\</b> all IRenderSystems, so behavior-rendered content always draws on top of system-rendered content.
ResetStart() Clears the start-failed state so that OnStart() will be retried on the next tick. Use this to recover from a transient initialization failure \(e\.g\., a required service that was not ready on the first frame\).
Update\(GameTime\) Called every frame if enabled.