Unsafe API
So far, we used the type-safe, generic API of Ark throughout.
However, there may be use cases where component types are not known at compile-time,
like serialization and de-serializations.
For these cases, Ark offers an unsafe, ID-based API.
It is accessible via ecs.World.Unsafe
.
Component IDs
Internally, each component type is mapped to an ecs.ID
.
We don’t see it in the generic API, but we can use it for more flexibility in the ID-based API.
IDs can be obtained by the function ecs.ComponentID
.
If a component is not yet registered, it gets registered upon first use.
1world := ecs.NewWorld()
2
3posID := ecs.ComponentID[Position](&world)
4velID := ecs.ComponentID[Velocity](&world)
5
6_, _ = posID, velID
Creating entities
Entities are created with ecs.Unsafe.NewEntity
, giving the desired component IDs:
1entity := world.Unsafe().NewEntity(posID, velID)
2_ = entity
Filters and queries
Filters and queries work similar to the generic API, but also component IDs instead of generics:
1filter := ecs.NewFilter(&world, posID, velID)
2
3query := filter.Query()
4for query.Next() {
5 pos := (*Position)(query.Get(posID))
6 vel := (*Velocity)(query.Get(velID))
7 pos.X += vel.X
8 pos.Y += vel.Y
9}
Important
Note the type casts! These are required because ecs.Query.Get
returns an unsafe.Pointer
to the underlying component storage.
Extra care should be taken here, because this is a common source of bugs and the cast is not checked for the correct type.
Component access
Components of entities can be accessed outside queries using ecs.Unsafe.Get
/ecs.Unsafe.Has
:
1entity := world.Unsafe().NewEntity(posID, velID)
2
3pos := (*Position)(world.Unsafe().Get(entity, posID))
4_ = pos
Important
Again, note the type cast! See above for details.
Component operations
Components can be added and removed using methods of ecs.Unsafe
:
1entity := world.NewEntity()
2
3world.Unsafe().Add(entity, posID, velID)
4world.Unsafe().Remove(entity, posID, velID)
Limitations
Besides not being type-safe (i.e. you can cast to anything without an immediate error), the unsafe API has a few limitations:
- It is slower than the type-safe API.
- Newly added components can’t be initialized directly.
ecs.Unsafe.Get
must be used for initialization. - There are currently no batch operations provided for the unsafe API.