Очень часто возникает проблема с обработкой ссылок на игровые объекты (назову эти объекты сущностями). Иногда речь идёт об отношениях «предок-потомок» между сущностями. Бывает, что полезно сохранить ссылку на объект при работе с данными о событиях, в классе планировщика задач и т.д.
Иногда можно обойтись простым указателем, ссылкой или std::reference_wrapper. Но при работе с обычными указателями и ссылками есть такая проблема: если вы ими пользуетесь, то должны быть уверены, что та сущность, на которую направлена ссылка, остаётся жива и не перемещается в памяти без уведомления тех объектов, что держат ссылку на неё. Пожалуй, в хорошо спроектированной программе это достижимо.
Однако устаревшие указатели/ссылки провоцируют некоторые гнуснейшие баги. Эти баги сложно отслеживать, не так легко выявить, и они могут обрушить вашу игру. Некоторые сущности могут занимать в памяти иные адреса, нежели предполагалось (например, после того, как вы перезагрузите уровень или решите заново создать с нуля всех врагов). Конечно, можно и вручную обновить все указатели на те сущности, на которые мы ранее ссылались. Но, определённо, это лучше делать автоматически, чтобы не оставалось никакой вероятности забыть какие-либо указатели, которые потом устареют.
Давайте рассмотрим, как можно решить все эти проблемы. Новейшее решение (связанное с сохранением ссылок в Lua) было обнаружено мною не так давно и побудило меня написать эту статью, но я хочу показать, что есть и другие способы решить эту задачу. Приступим!