Search Unity

Generating and managing terrains at runtime from code

Discussion in 'Scripting' started by tamaroq, Nov 5, 2013.

  1. tamaroq

    tamaroq

    Joined:
    Sep 14, 2013
    Posts:
    39
    I have been dealing with it lately. Documentation here is not really that helpful, so a resume of main things I found can be useful for some people here. Hope it helps.

    I use to use a permanent Game Object called GameManager to include the script that manages terrains.


    1. Generating a new terrain or referencing an existing one


    You have both possibilities. Both cases, you should reference Terrain and Terrain Data (the last one is not necessary, since terrain data can be accessed from terrain, but it's not a bad thing). To do so:


    public Terrain sceneTerrain;
    private TerrainData sceneTerrainData;
    ...
    void Awake()
    {
    sceneTerrainData = sceneTerrain.terrainData;
    }


    To reference an existing terrain just go to the inspector and drop the terrain in the added script, that's all. To generate a new terrain from code do something like:


    sceneTerrain = new Terrain();
    sceneTerrainData = new TerrainData();
    sceneTerrainData = sceneTerrain.terrainData;


    And that's all too. Of course, now you have to sculpt it.


    2. The problem with textures


    It's way easier to add textures in the inspector. So here I'm gonna consider that they're just added in the inspector to make it easier. If you're referencing an existing terrain, just go to it and add as many textures as you want.

    What happens if you're creating a terrain at runtime? It looks like there's not way to add textures to a terrain that doesn't exist yet. So here there's a little trick:

    1. Create a terrain in the inspector and add the textures to it.
    2. Create a prefab.
    3. Add the terrain to the prefab.
    4. Delete the terrain.

    Now we have a prefab with a terrain that has the textures preloaded. How do we use them? We jut must add to the script:


    public prefabSceneTerrain;
    ...
    sceneTerrainData.splatPrototypes = prefabSceneTerrain.terrainData.splatPrototypes;


    And the textures loaded in the prefab are copied to the new terrain. Of course, you should drop the prefab in the script in the inspector so it's referenced.


    3. The key properties: size, lies and videotapes :D


    The size related properties are easily handled at runtime.

    sceneTerrainData.alphamapResolution defines the resolution of the splatmap.
    sceneTerrainData.heightmapResolution defines the resolution of the heightmap.
    sceneTerrainData.size defines the size of the terrain in units.

    What's the difference and how to use them?

    Size is a Vector3 object that defines the size of the terrain in the gameworld. If we change it and check what happens in the scene view, we'll see the terrain 'stretching' as it was elastic. But this is not gonna affect to the resolution of the terrain. A terrain with a low resulotion made bigger is just... a bigger terrain with a low resolution.

    So, let's say we make it:

    sceneTerrainData.size = new Vector3(howLongIsTheTerrain, howHighIsTheTerrain, howWideIsTheTerrain);

    Yeap, the height goes in the "Y" coordinate. Keep this in mind, since this is a very easy way to exagerate/reduce the heightness/slopeness of the terrain.

    The height resolution is the resolution of the cloud of points that defines the terrain. It's like the number of polygons in a mesh after retopologizing: the more, the smoother the terrain, the screwed performance. Alphamap resolution is gonna be the resolution of the alphamap, that places different textures in the map. The more, the more variability of textures and realism in the terrain, the screwed the performance too.

    Those three properties don't need to be the same. So, let's say that we have

    sceneTerrainData.size = new Vector3(1024, 128, 1024);
    sceneTerrainData.alphamapResolution = 2048;
    sceneTerrainData.heightmapResolution = 512 + 1;

    That would mean that the terrain is 1024 units long. That will relate to objects scales, velocities (if the terrain is bigger, you'll move slowly there unless you change velocities) and similar stuff.

    Alphamap resolution is 2048. That's a nice one (maximum is 4096). That means that you'll be able to create quite a detailed textured surface.

    Heighmap resolution is 512 (you must add one unit more when setting this property. Don't ask me why is needed because I have no idea, just do it). It means that the terrain can feel more "polygonal", though this is gonna be your choce: detail vs performance.


    TO BE CONTINUED...
     
    Last edited: Nov 5, 2013