S&box Wiki

Event System

The event system is like the Hook system in Garry's Mod. It allows you to register functions on classes to receive a callback on certain global events.

Setting up your Class

Entities and panels are automatically registered/unregistered for you - for everything else, you just need to call Event.Register and Event.Unregister:

public class TeamManager { public TeamManager() { Event.Register( this ); // Do this on things that aren't entities or panels } [GameEvent.Tick] public void OnTick() { Log.Trace( "blah" ); } ~TeamManager() { Event.Unregister( this ); } }

Registering a Callback

Adding a [GameEvent.*] or [Event.*] attribute will add it to the list to be called.

[GameEvent.Tick.Server] public void MyCallback() { // will get called every server tick }

Built-in Events

The various events called from the engine currently:

Build Input

Called clientside every frame to process input and encode outputs into a user command.

[GameEvent.Client.BuildInput] public void MyBuildInput() { }

Client Disconnect

Called when a client disconnects.

[GameEvent.Server.ClientDisconnect] private void ClientDisconnect( ClientDisconnectEvent e ) { Log.Info( e.Client ); }

Client Joined

Called when a client joins.

[GameEvent.Server.ClientJoined] private void ClientJoined( ClientJoinedEvent e ) { Log.Info( e.Client ); }


Called just before the beginning of a rendering frame.



Called every server or client tick (60 times a second by default).

[GameEvent.Tick] [GameEvent.Tick.Server] [GameEvent.Tick.Client]

Physics Step

Called before each physics step, this is usually every tick but can be more depending on PhysicsSubSteps.


Called after each physics step.



Called each time your C# is hotloaded after successful recompile.


Post Entity Spawn

Called after all map entities have spawned in, including after map cleanups.


Custom Events

You can register your own custom event callbacks and call them.

[Event( "mygame.gameover" )] public void OnGameOver() { } public void DoGameOver() { Event.Run( "mygame.gameover" ) }

Event Arguments

Events can pass up to three arguments too.

[Event( "mygame.gameover" )] public void OnGameOver( Player winner ) { } public void DoGameOver( Player winner ) { Event.Run( "mygame.gameover", winner ) }

Event Attributes

If you want, you can also make your own custom EventAttributes (like [Event.Tick]) and use them to register handlers. The behavior is the same as raw event names but they have all the benefits of a type (picked up by IntelliSense, checked at compile time, etc.)

// Defining the event type public static class GameEvent { public const string Custom = "custom"; public class CustomAttribute : EventAttribute { public CustomAttribute() : base( Custom ) { } } } // Register it like this [GameEvent.Custom] public void OnCustomEvent() { // do something } // Fire it like this Event.Run( GameEvent.Custom );

Defining Method Arguments

When using custom event attributes you can define the required method arguments. This way, any methods that listen for this event must have matching arguments.

// This event requires a string as the first argument. [MethodArguments( typeof( string ) ) public class CustomAttribute : EventAttribute { public CustomAttribute() : base( Custom ) { } }