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 World.Unsafe.
Component IDs
Internally, each component type is mapped to an 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 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)Creating entities
Entities are created with Unsafe.NewEntity, giving the desired component IDs:
entity := world.Unsafe().NewEntity(posID, velID)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 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 Unsafe.Get/Unsafe.Has:
entity := world.Unsafe().NewEntity(posID, velID)
pos := (*Position)(world.Unsafe().Get(entity, posID))Important
Again, note the type cast! See above for details.
Component operations
Components can be added and removed using methods of 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.
Unsafe.Getmust be used for initialization. - There are currently no batch operations provided for the unsafe API.