Entities & Components
Entity is the entity the script is attached to, and Registry is the world’s
component store. This page covers working with this entity. To work with other
entities, see The World API.
Components
Section titled “Components”Component types come from C++ through reflection, so you
refer to them by name (STransformComponent, SRigidBodyComponent, and so on)
as a generic type argument. You reach a component through Registry, passing the
entity it lives on.
// Read this entity's rigid body, if it has one.SRigidBodyComponent? Body = Registry.TryGet<SRigidBodyComponent>(Entity);if (Body != null){ Body.Mass = 5.0f;}
// Add a mesh component and configure it in place.SStaticMeshComponent Mesh = Registry.Emplace<SStaticMeshComponent>(Entity)!;
Registry.Remove<SBillboardComponent>(Entity);| Method | Returns |
|---|---|
Registry.Get<T>(Entity) | The component; throws if absent |
Registry.TryGet<T>(Entity) | The component, or null |
Registry.Has<T>(Entity) | bool |
Registry.Emplace<T>(Entity) | Adds the component if missing and returns it (idempotent) |
Registry.Remove<T>(Entity) | bool (whether one was removed) |
The returned wrapper points at the live component, writing its fields writes through to the entity’s data. A component’s own methods and fields depend on its type; see Entities & Components for the catalog.
Caching a component with [RequireComponent]
Section titled “Caching a component with [RequireComponent]”Registry.Get crosses into native code each call, so for a component you touch
every frame, cache it. Mark a component-typed field [RequireComponent] and the
engine resolves it once (adding the component if missing) and assigns it before
OnReady.
public sealed class Mover : EntityScript{ [RequireComponent] private SRigidBodyComponent _Body = null!;
public override void OnUpdate(float DeltaTime) { _Body.LinearDamping = 0.1f; // no per-frame lookup }}Transform is already cached for you this way. It’s every entity’s
STransformComponent, resolved once.
Identity
Section titled “Identity”| Member | What it is |
|---|---|
Entity.Id | This entity’s raw id (a uint) |
Entity.IsNull | true for the null handle |
World.GetEntityName(Entity) | This entity’s name |
World.DestroyEntity(Entity) | Removes this entity |
World.DuplicateEntity(Entity) | Deep-copies it, returns the new entity |
Transform
Section titled “Transform”Transform is the live STransformComponent. Most methods work in local
space (relative to the parent); the World variants resolve through the parent
chain. Getters return FVector3 / FQuat.
FVector3 Here = Transform.GetLocalLocation(); // local-space positionTransform.SetLocalLocation(new FVector3(0, 2, 0)); // local-spaceFVector3 World = Transform.GetWorldLocation(); // resolved world positionTransform.Translate(new FVector3(0, 0, 1));Transform.AddYaw(90.0f); // degrees; also AddPitch, AddRollTransform.SetLocalRotationFromEuler(new FVector3(0, 90, 0));| Method | Space | Returns |
|---|---|---|
GetLocalLocation() / SetLocalLocation(v) | local | FVector3 |
GetLocalRotation() / SetLocalRotation(q) | local | FQuat |
GetLocalScale() / SetLocalScale(v) | local | FVector3 |
GetWorldLocation() / GetWorldRotation() / GetWorldScale() | world | |
GetLocalRotationAsEuler() / SetLocalRotationFromEuler(e) | local | degrees |
AddLocalRotationFromEuler(e) | local | degrees |
Translate(delta) | local | FVector3 |
AddYaw(deg) / AddPitch(deg) / AddRoll(deg) | local | |
GetForward() / GetRight() / GetUp() | world | FVector3 |
SetWorldTransform(t) | world |
Hierarchy
Section titled “Hierarchy”Parent and child links live on World, keyed by entity.
Entity Parent = World.GetParent(Entity); // Entity.Null if noneWorld.SetParent(Child, Entity); // reparent, preserving world transformWorld.DetachFromParent(Entity); // detach to the world rootEntity Root = World.GetRootEntity(Entity); // top of this entity's treeCamera
Section titled “Camera”If this entity has a camera, you can read and tune it through its component.
SCameraComponent Camera = Registry.Get<SCameraComponent>(Entity);Camera.SetFOV(70.0f);World.GetActiveCamera() returns the world’s current view camera. To make a
camera follow another entity, add an SCameraFollowComponent and set its target
(see Cameras).
Editable properties
Section titled “Editable properties”Expose a field to the editor with the [Property] attribute. It appears in the
entity’s C# Script section in the Details panel, and you read or write it
like any field. The field’s type picks the widget: a numeric drag, a vector
or color picker, an enum dropdown, an asset or entity picker, a nested struct, a
resizable list, and so on.
[Property(Category = "Movement", Min = 0, Max = 20, Units = "m/s", Tooltip = "Top speed.")]public float Speed = 5.0f;
[Property(Color = true)] public FVector3 Tint = new(1, 1, 1);
// Typed asset and entity references draw a searchable picker from their type.[Property] public TSoftObjectPtr<CStaticMesh> Mesh;[Property] public Entity Target;Every [Property] key is optional.
| Key | Effect |
|---|---|
Category = "X" | Groups the field under a collapsible header. Nest with "A|B". |
Tooltip = "X" | Hover help on the field. |
Name = "X" | Renames the field; this is both its inspector label and its saved key. |
Min = n / Max = n | Clamp range for a numeric field. |
Units = "X" | Unit suffix after a numeric value, e.g. "m/s". |
Color = true | Draws an RGBA color picker for an FVector3 / FVector4 instead of drag fields. |
Related attributes control persistence and hot reload.
| Attribute | Effect |
|---|---|
[Serialize] | Persists the field with the entity without showing it in the inspector. |
[Hide] | Keeps the field from ever being serialized or shown. |
[Alias("OldName")] | A prior member name, so a saved value still loads after you rename the field. Repeatable. |
[SkipHotReload] | Resets the field to its default on a C# hot reload instead of carrying the old value. Also valid on the script class to reset all of its properties. |
Instanced properties
Section titled “Instanced properties”An instanced property holds an owned instance of a type you pick in the
inspector. Mark a [Property] field with [Instanced] and the Details panel
shows a type picker of the concrete classes that derive from the field’s
declared type. Choose one and its own [Property] members edit inline, right
below the picker. It is the value-type analog of swapping in a different
behavior object per entity.
// A family of behaviors. The field is typed as the base (here an interface).public interface ICommand { }
public sealed class AttackCommand : ICommand{ [Property(Min = 0)] public float Damage = 10.0f; [Property] public string Target = "Enemy";}
public sealed class WaitCommand : ICommand{ [Property(Min = 0, Units = "s")] public float Seconds = 1.0f;}
public sealed class Enemy : EntityScript{ // The picker offers AttackCommand and WaitCommand; the chosen one edits inline. [Property(Category = "AI"), Instanced] public ICommand Command;}The declared type can be an interface, an abstract class, or a concrete base class. When it is concrete, the base type is itself one of the choices.
A candidate type must be default-constructible (have a public parameterless constructor) so the editor and the loader can create it. The chosen value persists and round-trips by the concrete type’s name, so it survives save, reload, and hot reload even though the rest of the picker is rebuilt each time.
Arrays of instanced objects (List<ICommand>) are not supported yet; use a
single instanced field.