Ресурсы: загрузка и независимые копии
Различайте Entity и Resource, учитывайте кэш загрузки и создавайте отдельный материал для экземпляра.
Entity и Resource
Entity находится в иерархии и получает события жизненного цикла. Resource хранит данные: материал, меш, текстуру, звук или упакованную иерархию PackedEntity. Ресурс сам по себе не добавляется в дерево через AddChild().
| Данные | Представление |
|---|---|
| Уровень или префаб | .rscene / .rprefab, класс PackedEntity |
| Текстовый ресурс движка | .rdata |
| Бинарный ресурс движка | .rbin |
| Исходное изображение, модель, звук | Собственный формат с импортом, например PNG, GLB, WAV |
Не любой файл — Resource: произвольный JSON или текст читают через файловый API. asset:// указывает внутрь проекта, user:// — в доступный для записи каталог данных пользователя.
Загрузка и кэш
ResourceLoader.Load(path) синхронно получает ресурс. По умолчанию используется CacheMode.Reuse: существующий ресурс из кэша может вернуться тому же вызывающему коду. Пока ресурс используется, повторная загрузка не гарантирует независимой копии. Другие режимы кэша меняют это поведение; выбирайте их намеренно.
Load<T>() выполняет приведение типа: несовместимый загруженный ресурс вызывает InvalidCastException. Для внешнего или выбираемого пользователем пути сначала загрузите без generic-параметра и проверьте is. Проверяйте отказ до обращения к свойствам; сам факт существования файла не гарантирует нужный тип.
Загрузка PackedEntity ещё не создаёт игровые объекты. Для этого нужны Instantiate() и AddChild(). Несколько экземпляров префаба могут ссылаться на один и тот же материал.
Независимый цвет одного объекта
Нужен MeshInstance3D с мешем и StandardMaterial3D на поверхности 0. Для примера подойдёт BoxMesh с назначенным материалом. Прикрепите IndependentTint.cs:
using Reckfell;
public partial class IndependentTint : MeshInstance3D
{
[Export] public Color Tint { get; set; } = new Color(0.2f, 0.5f, 1.0f);
public override void _Ready()
{
if (Mesh == null || Mesh.GetSurfaceCount() == 0 ||
GetActiveMaterial(0) is not StandardMaterial3D shared)
{
ReckfellApi.PushWarning("Assign a mesh with a StandardMaterial3D on surface 0.");
return;
}
var unique = (StandardMaterial3D)shared.Duplicate();
unique.AlbedoColor = Tint;
SetSurfaceOverrideMaterial(0, unique);
}
}После сборки и запуска цвет изменится только у этого экземпляра. Исходный материал остаётся прежним. Здесь копируется сам материал; текстуры и другие вложенные ресурсы могут оставаться общими. Duplicate(true) и флаги отдельных свойств имеют дополнительные правила — не считайте любую копию полностью независимым графом данных.
Ресурс на экземпляр префаба
ResourceLocalToScene = true, установленное в шаблоне до создания экземпляров, позволяет движку локализовать ресурс при PackedEntity.Instantiate(). Включение флага у уже используемого ресурса не создаёт задним числом отдельные материалы для существующих объектов. Для явной локальной правки проще создать копию и назначить её конкретному экземпляру.
Для больших загрузок изучите ResourceLoader.LoadThreadedRequest() и проверку статуса. Фоновое чтение ресурса не делает произвольные изменения дерева потокобезопасными: создание и присоединение игровых Entity выполняйте на главном потоке.
Если перекрасились все объекты, ищите общий ресурс. Если код меняет материал меша вместо конкретного объекта, используйте override материала у MeshInstance3D, как в примере. Справочник Resource, ResourceLoader.