03 — Aspects¶
Aspects group related read/write component operations into a single reusable struct, instead of listing individual component parameters.
Source: com.trecs.core/Samples~/Tutorials/03_Aspects/
What it does¶
Boids move in straight lines and wrap around a bounded area, rotated to face their movement direction.
Schema¶
Components¶
Position from Common/, plus Velocity and Speed defined in this sample. The template also pulls in PrefabId / GameObjectId via the RenderableGameObject base.
Tags & template¶
public struct Boid : ITag { }
public partial class BoidEntity
: ITemplate,
IExtends<CommonTemplates.RenderableGameObject>,
ITagged<SampleTags.Boid>
{
Position Position = default;
Velocity Velocity;
Speed Speed;
ColorComponent Color = new(UnityEngine.Color.white);
PrefabId PrefabId = new(AspectsPrefabs.Boid);
}
Systems¶
BoidMovementSystem¶
Defines an aspect and iterates over it:
public partial class BoidMovementSystem : ISystem
{
public void Execute()
{
foreach (var boid in Boid.Query(World).MatchByComponents())
{
boid.Position += World.DeltaTime * boid.Speed * boid.Velocity;
}
}
partial struct Boid : IAspect, IRead<Velocity, Speed>, IWrite<Position> { }
}
The Boid aspect provides:
ref readonly float3 Velocity(read-only, unwrapped fromVelocitycomponent)ref readonly float Speed(read-only, unwrapped fromSpeedcomponent)ref float3 Position(read-write, unwrapped fromPositioncomponent)
BoidWrapSystem¶
Wraps boids that go out of bounds. [ExecuteAfter] ensures it runs after movement:
[ExecuteAfter(typeof(BoidMovementSystem))]
public partial class BoidWrapSystem : ISystem
{
readonly float _halfSize;
public BoidWrapSystem(float areaSize)
{
_halfSize = areaSize / 2f;
}
[ForEachEntity(MatchByComponents = true)]
void Execute(in Boid boid)
{
ref var p = ref boid.Position;
if (p.x > _halfSize) p.x -= _halfSize * 2;
else if (p.x < -_halfSize) p.x += _halfSize * 2;
if (p.z > _halfSize) p.z -= _halfSize * 2;
else if (p.z < -_halfSize) p.z += _halfSize * 2;
}
partial struct Boid : IAspect, IWrite<Position> { }
}
BoidPresenter (variable update)¶
Reads position and velocity, then updates the GameObject transform to face the movement direction.
Concepts introduced¶
- Aspects —
partial structimplementingIAspect,IRead<T>,IWrite<T>. See Aspects. [Unwrap]components expose their inner value type through aspect properties. See Components.- Multiple aspects per system — different systems can define different aspect views over the same components.
- Read vs Write —
IRead<T>providesref readonly,IWrite<T>providesref. Aspect.Query(World).MatchByComponents()vs[ForEachEntity]— two ways to drive iteration over an aspect. See Queries & Iteration.