Как правильно делать копию эталонного объекта в Unity?

Необходимо при посещении новой области игроком создавать случайный ландшафт. На данный момент пытаюсь решить задачу так: на карте присутствует скрытый объект ландшафта, от которого делается клон, которому уже присваивается случайная карта высот:

public class ChunkLoader : MonoBehaviour
{
    public Terrain flat;

    void Start()
    {
        Terrain terrain = Instantiate(flat, new Vector3(0, 0, 0), Quaternion.identity);
        HMapGenerator(terrain);
    }

    Terrain HMapGenerator(Terrain terrain)
    {
        // ... //
        terrain.terrainData.SetHeights(0, 0, heights);
        return terrain;
    }
}

Однако, сколько я не искал, так и не обнаружил свойства или метода, с помощью которой клон можно отобразить на карте. Либо я в принципе неправильно решаю задачу, либо что-то упустил.


Ответы (1 шт):

Автор решения: Risto

В этом примере было сразу две ошибки.

Первая - нет никакой причины оставлять объект на сцене. После создания и настройки эталона достаточно было создать в проекте папку Assets/Prefabs и перетащить в неё эталон их иерархического древа сцены. После этого объект со сцены можно удалить, а эталон брать по необходимости, из файлов проекта.

Вторая - создавая копию объекта следует помнить, что она обладает всеми свойствами эталона, в том числе и ссылками на другие компоненты, которые вы не копировали. В данном конкретном случае объект Terrain связан с тем же компонентом TerrainData, что и префаб, и эти данные сохраняются на диске отдельным файлом. В результате, эта строчка:

terrain.terrainData.SetHeights(0, 0, heights);

изменяет общую карту высот копии и оригинала, что сводит на нет всю затею.

Решением проблемы является создание нового объекта класса TerrainData:

TerrainData tdata = new TerrainData();

изменение его так, как вам нужно, а затем уже создание из него игрового объекта Terrain:

GameObject terrobj = Terrain.CreateTerrainGameObject(tdata);

Затем создайте создайте пустой игровой объект на вашей сцене и присоедините к нему свой скрипт.

→ Ссылка