menu_bookDocumentation

Scene Events: Interface-Based Broadcasting and Listening

calendar_today May 20, 2026 schedule ~1 min read person PatrickJr verified 50

s&box uses interface-based events to broadcast and listen to events within a scene. Events are sent to active Components and GameObjectSystems — they are NOT sent over the network.

Defining an Event Interface

CSHARP
public interface IPlayerEvent : ISceneEvent<IPlayerEvent>
{
    void OnSpawned( Player player ) { }
    void OnDied( Player player ) { }
    void OnTakeDamage( Player player, float damage ) { }
}

Inheriting from ISceneEvent<T> provides a cleaner posting syntax. Default implementations let listeners only implement the events they care about.

Broadcasting Events

Post to all listeners in the scene:

CSHARP
IPlayerEvent.Post( x => x.OnSpawned( playerThatSpawned ) );

Post to a specific GameObject only:

CSHARP
IPlayerEvent.PostToGameObject( player.GameObject, x => x.OnSpawned( player ) );

Or use the lower-level API directly:

CSHARP
Scene.RunEvent<IPlayerEvent>( x => x.OnSpawned( playerThatSpawned ) );

Advanced Broadcasting Patterns

CSHARP
// Modify a value via event listeners
float damage = 100.0f;
Scene.RunEvent<IDamageModifier>( x => x.ModifyDamage( ref damage ) );

// Collect values from listeners
List<Vector3> points = new();
Scene.RunEvent<IDamageProvider>( x => x.GetDamagePoint( points ) );

// Directly manipulate components
Scene.RunEvent<SkinnedModelRenderer>( x => x.Tint = Color.Red );

Listening to Events

Implement the interface on any Component:

CSHARP
public class CameraWeapon : Component, IPlayerEvent
{
    void IPlayerEvent.OnTakeDamage( Player player, float damage )
    {
        // React to player taking damage
    }
}

Events are also received by GameObjectSystems that implement the interface.

Was this helpful?