01 — Hello Entity¶
The simplest Trecs sample — a spinning cube. Introduces the fundamental building blocks: components, tags, templates, systems, and world setup.
Source: Samples/01_HelloEntity/
What It Does¶
A cube rotates continuously around the Y axis. The rotation speed is configured when the system is created.
Schema¶
Components¶
The GameObjectId component (from Common) maps the entity to a Unity GameObject.
Tags¶
Template¶
public partial class SpinnerEntity : ITemplate, IHasTags<SampleTags.Spinner>
{
public Rotation Rotation = new(quaternion.identity);
public GameObjectId GameObjectId;
}
Systems¶
SpinnerSystem (Fixed Update)¶
Rotates all entities that have a Rotation component:
public partial class SpinnerSystem : ISystem
{
readonly float _rotationSpeed;
public SpinnerSystem(float rotationSpeed)
{
_rotationSpeed = rotationSpeed;
}
[ForEachEntity(MatchByComponents = true)]
void Execute(ref Rotation rotation)
{
float angle = World.DeltaTime * _rotationSpeed;
rotation.Value = math.mul(rotation.Value, quaternion.RotateY(angle));
}
}
Uses MatchByComponents = true to iterate all entities with Rotation, regardless of tags.
SpinnerGameObjectUpdater (Variable Update)¶
Syncs the ECS rotation to the Unity transform:
[VariableUpdate]
public partial class SpinnerGameObjectUpdater : ISystem
{
readonly GameObjectRegistry _gameObjectRegistry;
public SpinnerGameObjectUpdater(GameObjectRegistry gameObjectRegistry)
{
_gameObjectRegistry = gameObjectRegistry;
}
[ForEachEntity(MatchByComponents = true)]
void Execute(in GameObjectId id, in Rotation rotation)
{
var go = _gameObjectRegistry.Resolve(id);
go.transform.rotation = rotation.Value;
}
}
Marked [VariableUpdate] because it touches Unity GameObjects — rendering should happen at the display frame rate, not the fixed timestep. Though in this case it doesn't matter since rotation is updated in fixed and we aren't using interpolation in this sample.
World Setup¶
var world = new WorldBuilder()
.AddEntityType(SampleTemplates.SpinnerEntity.Template)
.Build();
world.AddSystems(new ISystem[]
{
new SpinnerSystem(rotationSpeed: 2f),
new SpinnerGameObjectUpdater(gameObjectRegistry),
});
// Initialize is called separately (via the initializables list)
// Entity creation happens in SceneInitializer.Initialize:
var world = world.CreateAccessor();
world.AddEntity<SampleTags.Spinner>()
.Set(gameObjectRegistry.Register(cube.gameObject));
Concepts Introduced¶
- Components are unmanaged structs implementing
IEntityComponent - Tags are empty structs implementing
ITagthat classify entities - Templates declare which components and tags an entity has
- Systems implement
ISystemand use[ForEachEntity]for iteration [VariableUpdate]separates rendering from simulationMatchByComponentsiterates by component presence instead of tags