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.
world := ecs.NewWorld()
posID := ecs.ComponentID[Position](&world)
velID := ecs.ComponentID[Velocity](&world)
_, _ = posID, velID
Creating entities
Entities are created with ecs.Unsafe.NewEntity
, giving the desired component IDs:
entity := world.Unsafe().NewEntity(posID, velID)
_ = entity
Filters and queries
Filters and queries work similar to the generic API, but also component IDs instead of generics:
filter := ecs.NewUnsafeFilter(&world, posID, velID)
query := filter.Query()
for query.Next() {
pos := (*Position)(query.Get(posID))
vel := (*Velocity)(query.Get(velID))
pos.X += vel.X
pos.Y += vel.Y
}
Important
Note the type casts! These are required because ecs.UnsafeQuery.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
:
entity := world.Unsafe().NewEntity(posID, velID)
pos := (*Position)(world.Unsafe().Get(entity, posID))
_ = pos
Important
Again, note the type cast! See above for details.
Component operations
Components can be added and removed using methods of ecs.Unsafe
:
entity := world.NewEntity()
world.Unsafe().Add(entity, posID, velID)
world.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.