Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/facepunch/sbox-public/llms.txt

Use this file to discover all available pages before exploring further.

Every game object in s&box gets its behaviour from components — C# classes that extend Component and override lifecycle methods. This page explains how to structure a component, which lifecycle methods are available, how to expose properties to the editor, and how to use tags, flags, and serialization attributes.

Class structure

A component is an abstract partial class. To create your own, create a new .cs file and extend Component:
using Sandbox;

public sealed class MyComponent : Component
{
    [Property] public float Speed { get; set; } = 100f;

    protected override void OnUpdate()
    {
        Transform.Position += Vector3.Forward * Speed * Time.Delta;
    }
}
s&box compiles your code automatically as you save, and hot-reload applies changes without restarting. See Hot Reload for details.

Lifecycle methods

The engine calls lifecycle methods on your component in a defined order. All methods are protected virtual and do nothing by default — override only what you need.
1

OnAwake

Called once when the component is first initialized, before it is enabled. Use this for one-time setup that does not depend on other components being active.
protected override void OnAwake()
{
    // Runs once at initialization
}
2

OnEnabled

Called after OnAwake, and again whenever the component transitions from disabled to enabled (including when the parent GameObject becomes active). Paired with OnDisabled.
protected override void OnEnabled()
{
    // Component or its parent became active
}

protected override void OnDisabled()
{
    // Component or its parent became inactive
}
3

OnStart

Called once before the first OnUpdate, but only after OnEnabled. This is the right place for logic that requires all components on the object to be initialized.
protected override void OnStart()
{
    // Runs once, just before the first Update
}
4

OnUpdate

Called every frame when the component is active. Time.Delta gives the elapsed time since the last frame.
protected override void OnUpdate()
{
    // Called every frame
}
5

OnFixedUpdate

Called on a fixed interval determined by the scene — the same interval at which physics are ticked. Use this for physics-related logic. Time.Delta inside OnFixedUpdate is the fixed timestep.
protected override void OnFixedUpdate()
{
    // Called at a fixed rate, aligned with the physics tick
}
6

OnPreRender

Called every frame before the scene is rendered. Not called on dedicated servers. Use this to update visual state (e.g. bone positions) before the camera draws.
protected override void OnPreRender()
{
    // Runs before rendering, not on dedicated servers
}
7

OnDestroy

Called once when the component or its parent GameObject is destroyed. Release any unmanaged resources here.
protected override void OnDestroy()
{
    // Cleanup before the component is removed
}

Summary table

MethodWhen calledPaired with
OnAwakeOnce, at initialization
OnEnabledOn enable or parent becoming activeOnDisabled
OnStartOnce, before the first OnUpdate
OnUpdateEvery frame
OnFixedUpdateFixed physics interval
OnPreRenderEvery frame, before rendering
OnDestroyOnce, when destroyed

Exposing properties to the editor

Decorate any field or property with [Property] to make it visible and editable in the s&box editor inspector. The engine serializes these values to the scene file automatically.
public sealed class Projectile : Component
{
    [Property] public float Speed { get; set; } = 400f;
    [Property] public float Damage { get; set; } = 25f;
    [Property] public GameObject ExplosionPrefab { get; set; }
}
Use properties ({ get; set; }) rather than fields so the editor can track changes and call OnValidate correctly.

OnValidate

OnValidate is called immediately after the component is deserialized from a scene file, and whenever a property is changed in the editor. Use it to clamp values or recompute derived state:
protected override void OnValidate()
{
    Speed = MathF.Max( 0f, Speed );
}

Tags

Tags are string labels attached to a GameObject. Your component can read and modify them via the Tags property, which is a shortcut for GameObject.Tags.
// Check for a tag
if ( Tags.Has( "player" ) )
{
    // ...
}

// Add or remove tags
Tags.Add( "immune" );
Tags.Remove( "immune" );
Use Scene.GetAllObjects( true ) combined with tag checks to filter objects efficiently, or use GameObject.GetComponentsInChildren<T>() when you need to find components by type.

Component flags

ComponentFlags control editor and networking behaviour for a component instance. Set them on Flags:
// Hide this component in the inspector
Flags = ComponentFlags.Hidden;

// Prevent this component from being saved to disk
Flags = ComponentFlags.NotSaved;

// Keep local — do not network this component as part of the scene snapshot
Flags = ComponentFlags.NotNetworked;

// Prevent this component from being cloned with the GameObject
Flags = ComponentFlags.NotCloned;
You can combine flags with the bitwise OR operator:
Flags = ComponentFlags.Hidden | ComponentFlags.NotSaved;

RequireComponent

Decorate a property with [RequireComponent] to ensure the engine automatically finds or creates the required component on the same GameObject when your component is initialized. This removes the need for null checks at startup.
public sealed class PlayerController : Component
{
    [Property, RequireComponent] public Rigidbody Body { get; set; }
}
If a Rigidbody already exists on the GameObject, it is assigned. If not, one is created automatically.

ExecuteInEditor

By default, components do not run their lifecycle methods (including OnUpdate) while the game is stopped in the editor. To opt in, implement the Component.ExecuteInEditor marker interface:
public sealed class GridOverlay : Component, Component.ExecuteInEditor
{
    protected override void OnUpdate()
    {
        // This now runs in the editor too
    }
}
Be careful with destructive logic in ExecuteInEditor components — the component runs in the editor scene, so changes to GameObjects have real effects on your scene file.

Accessing other components and the scene

From inside any component, you have direct shortcuts to the owning object and scene:
// The GameObject this component belongs to
GameObject go = GameObject;

// The scene this component is in
Scene scene = Scene;

// The transform of the parent GameObject
GameTransform t = Transform;

// Access other components on the same GameObject
var rb = Components.Get<Rigidbody>();

// Find components anywhere in the scene
var cam = Scene.GetAllComponents<CameraComponent>().FirstOrDefault();

Input system

Read player input inside OnUpdate with Input.Pressed and Input.Down.

Action Graphs

Wire up component lifecycle events to visual scripts without code.

Hot Reload

Understand how s&box applies code changes without restarting.

Component API reference

Full API reference for the Component base class.

Build docs developers (and LLMs) love