Components
A component is a C# class attached to a node. Nodes hold data about where something is; components decide what it is and how it behaves.
Declaring a component
Inherit from Component and give the class a public parameterless constructor (the default one is fine):
namespace Usercode;
public class Health : Component
{
public int maximum = 100;
public int Current { get; private set; }
public override void OnStart() => Current = maximum;
public void Damage(int amount)
{
Current = Math.Max(0, Current - amount);
if (Current == 0) Node!.IsActive = false;
}
}
Every component you declare appears in the Inspector's Add Component menu. Group it under a path with
[ComponentContextMenu("Gameplay/Health")].
A component's type is identified in scene files by a stable id. For your scripts it comes from the script's
.cs.meta file, created automatically the first time the script compiles; engine types declare it with
[TypeId("…")]. Either way, renaming the class or moving it to another namespace does not break saved scenes.
Lifecycle
| Callback | When |
|---|---|
OnAttached() |
Right after the component is attached to a node. |
OnAwake() |
Once, on first attachment — even when inactive. Resolve services here. |
OnEnable() |
The component becomes active; also right after OnAwake when it starts active. |
OnStart() |
Once, on the first frame the component is active, before its first update. |
OnFixedUpdate(float fixedDeltaTime) |
At a fixed 60 Hz step, as many times as the elapsed time requires. |
OnUpdate(float deltaTime) |
Once per frame. |
OnLateUpdate(float deltaTime) |
Once per frame, after every OnUpdate — for cameras that follow moving things. |
OnDisable() |
The component or its node becomes inactive. |
OnDetached() |
Right before the component leaves its node. |
OnDestroy() |
The component is removed or its node destroyed. |
Each frame the engine first starts any component that has not started yet, then runs the fixed steps, then
OnUpdate over the whole tree, then OnLateUpdate. Inactive nodes and components are skipped. An exception
thrown by a component is logged with the component's name and does not stop the game.
Activation
component.IsActive switches one component. node.IsActive switches a node: its components receive
OnEnable/OnDisable, and while it is inactive the engine skips the node and all of its descendants.
Talking to other components
var health = Node!.GetComponent<Health>(); // on the same node, or null
var all = Node.GetComponents<LightComponent>(); // every match on the node
var inChildren = Node.GetComponentsInChildren<Health>(); // the node and its descendants
bool hasCamera = Node.HasComponent<CameraComponent>();
var light = Node.AddComponent<LightComponent>(); // attach at runtime
Node.RemoveComponent(light);
To point at another node, component or data asset, declare a field of its type and drag it onto the slot in the Inspector — just like Unity:
public class Turret : Component
{
public Node? Target; // a node in the scene
public CameraComponent? Camera; // a component on another node
public List<Node?> Waypoints = []; // lists and arrays work too
public WeaponData? Weapon; // a data asset
}
The scene saves these as references, not copies, and wires them up when it loads — including references into
another scene loaded additively, which connect as soon as both scenes are loaded. A reference to a node or
component that has been destroyed reads as missing (ObjectReferences.IsMissing(target)) and is saved as empty.
A reference whose target is not loaded keeps its id, so saving the scene never loses it.
NodeRef<T>, ComponentRef<T> and AssetReference<T> still exist for references you want to resolve yourself,
on demand, with Resolve(sceneRoot) or LoadAsync(loader). To store a copy of an object instead of a reference,
mark the field [SerializeInline].
Engine services
Scripts reach engine services through RuntimeServices, which works the same in Play Mode and in exported games:
ISceneManager? scenes;
public override void OnAwake() => scenes = RuntimeServices.TryGet<ISceneManager>();
Services available to scripts: ISceneManager (scenes),
IAssetLoader (assets), IInputSource and
InputActionService (input) and LocaleService
(localization). The static facades Input,
InputActions and Localization wrap the common calls.
Attributes
| Attribute | On | Effect |
|---|---|---|
[ComponentContextMenu("Path/Name")] |
class | Places the component in the Add Component menu. |
[DisallowMultipleComponent] |
class | At most one per node. |
[RequireComponent(typeof(T))] |
class | Adding this component also adds T. |
[Hide] |
member | Hides a public member from the Inspector. |
[Show] |
member | Shows a non-public member. |
[ReadOnly] |
member | Shows the value without allowing edits. |
[Range(min, max)] |
number | Clamps edits and scrubbing. |
[NumericUpDown] |
number | Draws a spinner-style field. |
[Button] |
method | Draws a button that calls the parameterless method. |
[Expand(false)] |
member | Starts a group collapsed. |
[EnumLabel("…")] |
enum value | Overrides the label in dropdowns. |
Logging
Log.Logger is a standard Microsoft.Extensions.Logging.ILogger:
Log.Logger.LogInformation("Picked up {Item}", item.Name);
Log.Logger.LogWarning("Health is low: {Current}", Current);
Messages appear in Studio's Output panel and on the console of a running game.
Built-in components
| Component | Menu | Purpose |
|---|---|---|
CameraComponent |
Rendering/Camera | Perspective or orthographic view. The active camera with the highest Priority renders. |
FreeFlyCameraComponent¹ |
Rendering/Camera/Free Fly | WASD + mouse fly camera. |
FpsCameraComponent |
Rendering/Camera/FPS | First-person look and movement. |
OrbitCameraComponent |
Rendering/Camera/Orbit | Orbits a target point; scroll to zoom. |
FollowCameraComponent¹ |
Rendering/Camera/Follow | Follows a target node at an offset. |
¹ The four camera rigs (Free Fly, FPS, Orbit, Follow) come from the built-in brick
org.mass4.turian.cameras (namespace Turian.Cameras), which new projects install.
| LightComponent | Rendering/Light | Point or directional light. |
| ModelComponent | Rendering/Model | Draws an imported model, with per-submesh material overrides. |
| MeshComponent | Rendering/Mesh | Draws a single mesh. |
| UiDocumentComponent | UI/UI Document | Renders a .ui document on screen or in the world. See Game UI. |
| UiRaycasterComponent | UI/UI Raycaster | Makes a world-space UI document clickable. |