Экземпляры префабов
Разместите несколько экземпляров одного префаба и создайте экземпляр с проверкой типа в C#.
Префаб .rprefab хранит иерархию с одним корнем. Экземпляр — отдельная созданная иерархия. Два экземпляра одного ящика можно двигать независимо; материал или текстура внутри них при этом могут оставаться общим ресурсом.
Разместите экземпляры в редакторе
- Создайте префаб
Crate.rprefabс корнемEntity3Dи дочернимMeshInstance3D. ВMeshзадайтеBoxMesh, затем сохраните файл вProps. - Откройте уровень, например
Main.rscene, или префаб-контейнер, напримерMain.rprefab. Не размещайтеCrate.rprefabвнутри самого себя. - Откройте панель ресурсов Content сочетанием Ctrl + Space. Перетащите файл
Props/Crate.rprefabна нужного родителя в иерархии. Место панели зависит от раскладки; искать её слева или снизу не требуется. - Повторите, затем задайте экземплярам X =
-1.5и1.5. Сохраните документ.
Такой ящик только рисуется. Столкновения требуют физического тела и формы. Если ящики не видны при запуске, проверьте камеру и свет в уровне. Если редактор отклоняет вложение из-за циклической зависимости, откройте другой документ: префаб не может прямо или через другие префабы содержать собственный экземпляр.
Изменение исходного префаба распространяется на свойства экземпляров без локальных переопределений. Изменённое положение одного экземпляра хранится в содержащем его документе. Изменение общего материала может затронуть оба: для независимого материала сначала создайте его копию.
Создайте экземпляр из кода
Сохраните следующий вспомогательный класс в PrefabFactory.cs; прикреплять его к Entity не нужно. Вызывайте CreateProp() на главном потоке с действующим родителем Entity3D, который уже находится в дереве. Например: PrefabFactory.CreateProp("asset://Props/Crate.rprefab", this, new Vector3(0, 0, -2)) внутри скрипта Entity3D.
using Reckfell;
public static class PrefabFactory
{
public static Entity3D? CreateProp(
string path, Entity3D parent, Vector3 localPosition)
{
Resource loaded = ResourceLoader.Load(path);
if (loaded is not PackedEntity template || !template.CanInstantiate())
return null;
Entity instance = template.Instantiate();
if (instance is not Entity3D prop)
{
instance?.Free();
return null;
}
prop.Position = localPosition;
parent.AddChild(prop);
return prop;
}
}Метод возвращает созданную Entity3D или null. Положение локальное относительно родителя и устанавливается до AddChild(): обработчик _Ready() увидит его сразу. Если корень оказался 2D, уже созданная, но не присоединённая иерархия освобождается через Free().
Load() получает ресурс; Instantiate() создаёт иерархию; AddChild() вводит её в дерево и запускает жизненный цикл. Для заранее известного корня подходит Instantiate<Entity3D>(), но несовпадение типа вызывает InvalidCastException после создания. InstantiateOrNull<T>() также создаёт объект до проверки типа; он не является проверкой содержимого без создания.
Удаление и сохранение
Для присоединённого экземпляра используйте QueueFree(): удаление отложено, до конца кадра объект ещё может существовать. Для не присоединённого объекта, который вы только что создали и отклонили, здесь используется немедленное Free().
При размещении из панели ресурсов редактор задаёт владельца экземпляра для сохранения в текущем документе. Runtime-экземпляры из AddChild() не записываются в файл автоматически: этот вызов сам не задаёт Owner. Owner влияет на упаковку иерархии, но не заменяет GetParent(). Уровень .rscene и префаб .rprefab загружаются как PackedEntity; роль определяется путём ресурса. Создание, мировые координаты и удаление объектов.