ECS Resources
So far, we stored all data in components, associated to entities. However, sometimes this is not optimal. This particularly applies to non-ECS data structures, and “things” that appear only once in a model or game.
For these cases, Arche provides so-called
ecs.Resources
.
A resource can be thought of as a component that only appears once, globally,
in an
ecs.World
.
Resource types
Just like with components, any Go struct (or other Go type) can be a resource. An example:
1type Grid struct {
2 Data [][]ecs.Entity
3 Width int
4 Height int
5}
Resource IDs
Also analogous to components, resources are identified by a unique ID that can be obtained or registered using
ecs.ResourceID
:
1world := ecs.NewWorld()
2
3gridID := ecs.ResourceID[Grid](&world)
4_ = gridID
As with components, a resource is registered and assigned an ID on first use automatically.
Adding resources
The most simple way to add a resource to the world is the function
ecs.AddResource
:
1world := ecs.NewWorld()
2
3// Create the resource, and add a pointer to it to the world.
4grid := NewGrid(30, 20)
5ecs.AddResource(&world, &grid)
An ID is automatically assigned to type Grid
here, if it was not registered before with
ecs.ResourceID
.
ecs.AddResource
, however, is not particularly efficient.
It a resource needs to be added (and removed) repeatedly, use
ecs.World.Resources
:
1world := ecs.NewWorld()
2gridID := ecs.ResourceID[Grid](&world)
3
4// Create the resource, and add a pointer to it to the world.
5grid := NewGrid(30, 20)
6world.Resources().Add(gridID, &grid)
Accessing resources
Access to resources is obtained via
ecs.World.Resources
in the ID-based API,
and via
generic.Resource
in the generic API:
1world := ecs.NewWorld()
2
3// Create the resource, and add a pointer to it to the world.
4grid := NewGrid(30, 20)
5ecs.AddResource(&world, &grid)
6
7// Then, somewhere else in the code...
8gridRes := generic.NewResource[Grid](&world)
9grid2 := gridRes.Get()
10
11_ = grid2.Data[1][2]
1world := ecs.NewWorld()
2
3// Create the resource, and add a pointer to it to the world.
4grid := NewGrid(30, 20)
5ecs.AddResource(&world, &grid)
6
7// Then, somewhere else in the code...
8gridID := ecs.ResourceID[Grid](&world)
9grid2 := world.Resources().Get(gridID).(*Grid)
10
11_ = grid2.Data[1][2]
Note that in the ID-based example, we need to cast the pointer retrieved from
ecs.Resources.Get
to *Grid
, similar to the cast in ID-based component access.
However, the syntax is a bit different here as we cast an interface{}
,
rather than an unsafe.Pointer
for components.
As with components, the generic API is the recommended way for normal usage.