>>102150510
I suppose a pointer is a handle too (I use pointers in addition), but I mean using an integer as some identifier for data thats stored elsewhere like
template<typename T>
struct handle
{
int id = -1;
bool is_valid() const { return id != -1; }
};
So for example, you have a renderable handle. The renderable stores a model and a transform and some render settings. You use the renderable handle to update the renderable's data, such as updating the transform. The advantage is that the renderer doesnt care about who owns the renderables handles, it just has a bunch of renderables that it can iterate over to draw.
struct Renderable
{
Model* m = nullptr;
mat4 transform;
};
class Renderer
{
handle<Renderable> register_renderable();
void update_renderable(handle<Renderable> handle, Renderable data);
void remove_renderable(handle<Renderable> handle);
};
So anybody can own the renderable handle. If you're using a Unity/Unreal like component model, maybe a MeshComponent, BillboardComponent, or anything else owns a renderable handle. If youre making an RTS game with 1000s of units, you can skip the components and use straight handles to draw stuff. Its super flexible and decouples the owner from the data. The renderer is *never* going to iterate over the owners to pull data, owners are the only ones allowed to push data into handles.
Apply the handle pattern to more stuff: lights, decals, cubemaps, audio sources, particles, physics bodies, etc.
Its similar to ECS, but different. ECS components are never independent, theyre attached to more components, and the idomatic way of using ECS is to split component data into multiple arrays. You never do this with handles, all of the handle's internal data is in one struct, its an independent unit. ECS tries to be to generic and fails.