Skip to content

World Systems

A world system runs over the whole world, not a single entity. Where an entity system is a script attached to one entity that runs that entity’s behavior, a world system is created once per world and iterates entities itself, once per frame, just like an engine (C++) system. The two are different tools.

Entity systemWorld system
Instanceone per entity (C# Script component)one per world
this isthat entity’s scriptthe system (no entity)
Iteratesnothing (it is the entity)entities you query through the context
Good forone actor’s behaviora rule applied across many entities

Reach for a world system when a behavior is really a rule over a set of entities (spin everything tagged a certain way, drain every Health below zero) rather than logic that belongs to one actor.

A world system is a class that derives from EntitySystem and carries an [EntitySystem] attribute declaring its stage and priority. The attribute is what makes the type discovered and run; one instance is created per world automatically.

using LuminaSharp;
using Lumina;
namespace Game;
[EntitySystem(Stage = EUpdateStage.PrePhysics, Priority = 128)]
public sealed class SpinSystem : EntitySystem
{
public override void OnUpdate(SystemContext Context)
{
float Dt = Context.DeltaTime;
Context.Registry.View<STransformComponent>().Each((Entity E, STransformComponent Transform) =>
{
Transform.AddYaw(90.0f * Dt);
});
}
}

Override only what you need. All three receive the per-tick SystemContext.

MethodWhen it runs
OnStartup(SystemContext)Once, when the system is created for a world.
OnUpdate(SystemContext)Every frame, in its stage.
OnTeardown(SystemContext)Once, when the world (or this system) is torn down.

The system’s World property is also available, for the full World API.

A world system runs in one update stage, and systems within a stage run in priority order. These mirror the engine’s own pipeline, and they are the same pre- and post-physics phases an entity system can opt into.

EUpdateStageRuns
FrameStartStart of frame, before anything else.
PrePhysicsBefore the physics step (input, movement intent). The default.
DuringPhysicsAlongside the physics step.
PostPhysicsAfter physics resolves (react to results).
FrameEndEnd of frame.
PausedThe stage that ticks while the editor is idle (not playing).

Priority is an int, lower runs first, and 128 is the default (medium).

[EntitySystem(Stage = EUpdateStage.PostPhysics, Priority = 0)] // runs early in PostPhysics

SystemContext mirrors the C++ system context, exposing time, entity creation, and access to the live world’s component store.

MemberDoes
Context.DeltaTime / Context.TimeSeconds this frame / total world time.
Context.RegistryThe component store. Author views with Registry.View<...>().
Context.Create() / Context.Destroy(entity)Make or destroy an entity.
Context.SetEntityLocation(entity, v)Set an entity’s world-space location.
Context.DrawDebugLine(start, end, color)One-frame debug line (Dev/Debug only).

Registry.View<...>() is an entt-style typed view, every entity that has all of the listed components. Iterate it with .Each(...) or foreach, and pass an Exclude<...>() filter as the argument to skip entities that also have a component.

public override void OnUpdate(SystemContext Context)
{
EntityRegistry Registry = Context.Registry;
// Every entity with both components, excluding the frozen ones.
var View = Registry.View<STransformComponent, SVelocityComponent>(
EntityRegistry.Exclude<SFrozenTag>());
foreach ((Entity E, STransformComponent Transform, SVelocityComponent Velocity) in View)
{
Transform.Translate(Velocity.Value * Context.DeltaTime);
}
}

Views support arity 1–4 and an exclude filter of up to 3 types. The wrappers a view hands back are valid only for the current iteration step. Read out any field you need to keep, don’t store the wrapper.

Everything outside the entity set (physics, navigation, networking, debug drawing) is reached through the system’s World property, exactly as in entity systems, via World.Physics, World.Navigation, World.Net, World.Draw. See The World API.