Random Terrain Generator.

Discussion in 'Scripting' started by misterkid, Sep 18, 2012.

  1. misterkid

    misterkid

    New Member

    Joined:
    Feb 15, 2012
    Messages:
    79
    Hi,

    I've been busy trying to make a terrain generator by generator random heighmaps.
    I got so far I can generate a weird terrain.
    Like this
    PHP:
        void GenerateHeightMap()
        {
            
    tdTerrainData tTerrain.terrainData;
            
    w2 tdTerrainData.heightmapWidth;
            
    w2;
            
    w2;
            
    heightmap = new Texture2D(w,h);
            
    //ToDo Good Heightmaps!
            
    for(int i 0wi++)
            {
                for(
    int j 0wj++)
                {
                    
    //heightmap.SetPixel(i,j,new Color(baseHeight,baseHeight,baseHeight,1));
                    
    heightmap.SetPixel(i,j,new Color(Random.Range(0,baseHeight),Random.Range(0,baseHeight),Random.Range(0,baseHeight),1));
                }
                
    //heightmap.SetPixel(i,i,Color.white);
            
    }
            
            
    //Makemountain(6,3,0.1f); 
            
            
    heightmap.Apply();
            
    heightmapData tdTerrainData.GetHeights(00w2w2);
            
    mapColors heightmap.GetPixels();
            
    map = new Color[w2 w2];
        }
    My Make Mountain function

    PHP:
        void Makemountain(int x,int y,float mountianHeight)
        {
            
    int colorsAmount 32*32;
            
    float newHeightColor 0f;
            
    float newHeightSteps mountianHeight/32;// mountianHeight/colorsAmount; 
            
            
    Color[] mountainHeightMap = new Color[colorsAmount];
            for(
    int i 0colorsAmounti++)
            {
                
    newHeightColor += newHeightSteps;
                if(
    newHeightColor mountianHeight)
                    
    newHeightColor 0;
                
                
    Debug.Log(newHeightColor);
                
    mountainHeightMap[i] = new Color(newHeightColor,newHeightColor,newHeightColor,1);
            }
            
            
    heightmap.SetPixels(x,y,32,32,mountainHeightMap);
    }
    It failed epicly lol. My Math isn't really good I hope someone can help me out and explain it way :)


    I used http://wiki.unity3d.com/index.php?title=HeightmapFromTexture as example to load height maps :roll:

    Also I wanted to know how to generate Grass,Texture and tree's on a terrain.
    I did generate tree's as in adding new gameobjects but I want to use the terrain features :(

    Thanks in advance!
  2. misterkid

    misterkid

    New Member

    Joined:
    Feb 15, 2012
    Messages:
    79
  3. Windexglow2

    Windexglow2

    Member

    Joined:
    Sep 23, 2012
    Messages:
    89
    An alternative would be to use perlin/simplex noise. Here's a unity library for it.
    http://forum.unity3d.com/threads/68764-LibNoise-Ported-to-Unity

    I could throw in my code which generates terrain (size, distance between verts, verts per chunk all variable) but it isn't actual unity terrain.
    I think you can kind of hack-ishly generate unity terrain at runtime, but it isn't well documented and I also think it could crash easily.
    So look into that, maybe it's possible.

    Using a bitmap to store data though isn't too smart (I did it too:p). It's slow and storing pointless data. it may also be less accurate.
  4. misterkid

    misterkid

    New Member

    Joined:
    Feb 15, 2012
    Messages:
    79
    Hi,
    Well I already google perlin noise :( I don't really get it :S I just don't get the math behind it and how to apply it.
    If you can explain that or give me a link to understand it it would be awesome.(Wikipedia doesn't explain the math behind it :S)
  5. UnLogick

    UnLogick

    Unity Technologies

    Joined:
    Jun 11, 2011
    Messages:
    842
  6. natsirt16

    natsirt16

    New Member

    Joined:
    Sep 6, 2012
    Messages:
    14
    yah i got an idea you shoudl use what unlogic put above and set the terrain to repeat the terrain in any direction once the player moves to the border of the current terrain so it generates a terrain like that BUT it will not be the same :) but soem how get it to store the old terrain so if you go backwards you can go back to that terrain say if yoru house is there.
  7. WillJ

    WillJ

    New Member

    Joined:
    Aug 12, 2013
    Messages:
    2
    Here is a small script that might help you out :)

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class RandomTerrainGenerator : ScriptableWizard {
    7.    
    8.   //The higher the numbers, the more hills/mountains there are
    9.     private float HM = Random.Range(0, 40);
    10.    
    11.     //The lower the numbers in the number range, the higher the hills/mountains will be...
    12.     private float divRange = Random.Range(6,15);
    13.  
    14.     [MenuItem("Terrain/Generate Random Terrain")]
    15.     public static void CreateWizard(MenuCommand command)
    16.     {
    17.         ScriptableWizard.DisplayWizard("Generate Random Terrain", typeof(RandomTerrainGenerator));
    18.     }
    19.  
    20.     void OnWizardCreate()
    21.     {
    22.         if (G.GetComponent<Terrain>())
    23.         {
    24.             GenerateTerrain(G.GetComponent<Terrain>(), HM);
    25.         }
    26.     }
    27.    
    28.     //Our Generate Terrain function
    29.     public void GenerateTerrain(Terrain t, float tileSize)
    30.     {
    31.        
    32.         //Heights For Our Hills/Mountains
    33.         float[,] hts = new float[t.terrainData.heightmapWidth, t.terrainData.heightmapHeight];
    34.         for (int i = 0; i < t.terrainData.heightmapWidth; i++)
    35.         {
    36.             for (int k = 0; k < t.terrainData.heightmapHeight; k++)
    37.             {
    38.                 hts[i, k] = Mathf.PerlinNoise(((float)i / (float)t.terrainData.heightmapWidth) * tileSize, ((float)k / (float)t.terrainData.heightmapHeight) * tileSize)/ divRange;
    39.             }
    40.        }
    41.             Debug.LogWarning("DivRange: " + divRange + " , " + "HTiling: " + HM);
    42.         t.terrainData.SetHeights(0, 0, hts);
    43.     }
    44. }
    45.  
    1). Create a terrain, and keep it selected in the editor...
    2). Click on the "Terrain" tool in the editor
    3). Click on Generate Random Terrain



    This script has been tested, and I hope it helps...


    - Will
  8. doomguy95

    doomguy95

    New Member

    Joined:
    Oct 5, 2013
    Messages:
    2
    Hi, I've just trieed out WillJ's script. I havent got any experience in programming so i'm abit stuck. You see, whenever I try and add the script it says i cant. And in red at the bottom it says add a semiclono. I did but it is still broken. Proabbly because I put it in the wrong place. If you could i would really apriciate some help.
  9. WillJ

    WillJ

    New Member

    Joined:
    Aug 12, 2013
    Messages:
    2
    Sorry about my other script being a bit confusing. Since the time I posted that code, I have revised some of my methods and have done a bit (a lot) of research. For those of you who want a random terrain in unity, I have come up with a few of the best options for random terrain/world generation techniques and such. Now, before I list these options and some code for each, I would like to explain, that to achieve a smooth running minecraft-like random world/terrain in unity, it isn't necessarily hard to achieve, but it WILL take time. Depending on how much you want to code on your own, and how much you want to snip off of what I am providing is totally your choice, and you can use the code that I am providing in any way you want. Finally, on to the freakin code and whatnot.

    Methods For Random World/Terrain Generation:

    1). Voxel World Generation

    I really like this method, as it is much easier for survival games. For instance Minecraft (of 7 Days To Die). Minecraft runs on the LWJGL (Light-Weight-Java-Game-Library), as it is much harder to achieve 3-Dimensional graphics and world generation without using LWJGL (it will just take a lot longer to do what you want to do really). The blocks in Minecraft are breakable, craft-able, and place-able. If we were to do this in Unity3D, it would take us longer to achieve a dynamic voxel world (breakable, craft-able, and place-able blocks, trees, etc.), than it would for us to make a randomly generated terrain (default terrain in Unity), but it would allow us to make a highly dynamic world much easier with less hair tearing out, than us making a fully dynamic terrain in Unity. Really most of this doesn't matter depending on who you are. You may choose what you want, but in the end I really like voxel engines/worlds/terrains, especially the random ones... Our code will be a nice smooth voxel terrain, whereas Minecrafts' is not.
    If after that little article, you still don't understand what a voxel engine is, then you should check out these links/demos (or if you just want to learn more or screw around):

    http://terravol.com/demo1

    http://forum.unity3d.com/threads/198651-Tutorial-Procedural-meshes-and-voxel-terrain-C

    http://forum.unity3d.com/threads/177573-TerraVol-volumetric-voxel-terrain-system-Dig-holes-amp-caves-in-your-terrains!

    http://forum.unity3d.com/threads/93282-Question-about-the-engine-voxel-terrain!

    http://studentgamedev.blogspot.no/2013/08/unity-voxel-tutorial-part-1-generating.html

    http://studentgamedev.blogspot.no/2013/08/VoxelTutP2.html

    http://studentgamedev.blogspot.no/2013/09/unity-voxel-tutorial-part-3-perlin.html

    http://studentgamedev.blogspot.no/2013/09/unity-voxel-tutorial-part-4-destroying.html

    http://studentgamedev.blogspot.no/2013/10/unity-voxel-tutorial-part-5-3d-voxel.html

    http://studentgamedev.blogspot.no/2013/10/unity-voxel-tutorial-part-6-3d-voxels.html

    http://studentgamedev.blogspot.no/2013/10/unity-voxel-tutorial-part-7-modifying.html

    http://studentgamedev.blogspot.no/2013/11/unity-voxel-tutorial-part-8-loading.html

    https://sites.google.com/site/letsmakeavoxelengine/home

    $_6902895256400205067_2.png

    A wee bit of code!

    Sorry for those of you guys that like C#. I got a bit lazy and wrote in JavaScript. I'll work on a C# version :)

    PHP:
    #pragma strict

    private var rot Quaternion;
    rot.eulerAngles Vector3(000);

    //Our gameobject
    var terraincubeGameObject;
     
    function 
    Start (){

    //Our X and Z
    for (var px:float 0px 95px ++) {

    //Our Y
        
    for (var py:float 0py95py ++) {
     
    var 
    Perlin1 Mathf.PerlinNoise(px/8076);
    var 
    Perlin2 Mathf.PerlinNoise(py/8022);

    //How many cubes that will be instantiated.
    Instantiate(terraincubeVector3(py-100Perlin1*90*Perlin2px-100), rot);

    }


    /*************/
    /**  NOTE  **/
    //This is not an efficient method whatsoever, this is just an introduction to understanding Perlin Noise.
    /************/
    Yes, I know for those of you who don't have top o' the line PC's this is laggy, same here. I am going to make some sort of tutorial series on how to make a smoother Voxel Map, but I am really, really tired right now. It is around 1 AM here, so yeah. I am up late... Again... Just remember to attach and add the cubes, please. GOOD NIGHT TO ALL!
  10. HuskyPanda213

    HuskyPanda213

    Member

    Joined:
    Mar 24, 2013
    Messages:
    26
    You do not need to make this hard perlin noise stuff, just download terrain toolkit(it's free), and use my code:

    using UnityEngine;
    using System.Collections;

    public class PerlinTerrain : MonoBehaviour {

    //Toolkit instance.
    [SerializeField]TerrainToolkit kit;
    //Array of textures.
    [SerializeField]Texture2D sandTexture;
    [SerializeField]Texture2D grassTexture;
    [SerializeField]Texture2D rockTexture;
    [SerializeField]Texture2D cliffTexture;

    void Start() {
    //Check if we have the kit assigned;.
    if (kit == null) {
    //If there is not an instance assigned or on gameObject, return.
    if (!GetComponent<TerrainToolkit>())
    {
    return;
    }
    //Else assign kit to gameObject's toolkit.
    else
    {
    kit = GetComponent<TerrainToolkit>();
    }
    }
    //Generate the terrain.
    Generate();
    }

    void OnGUI(){
    if (GUILayout.Button ("Generate")) {
    Generate();
    }
    }

    public void Generate() {
    //Generate the perlin terrain.
    kit.PerlinGenerator((int)Random.Range(3,6),Random.Range(0.4f,0.9f),Random.Range(2,6), 1f);
    //Gives it a less smooth feel.
    kit.PerlinGenerator(4,4,4, 0.1f);
    //Creates arrays for stops.
    float[] slopeStops = new float[2];
    float[] heightStops = new float[4];
    Texture2D[] terrainTextures = new Texture2D[4];
    //Assigns values to the arrays.
    slopeStops[0] = 30f; slopeStops[1] = 70f;
    heightStops[0] = Random.Range(0.05f, 0.18f);
    heightStops[1] = Random.Range(0.19f, 0.49f);
    heightStops[2] = Random.Range(0.5f, 0.69f);
    heightStops[3] = Random.Range(0.7f, 0.89f);
    terrainTextures[0] = cliffTexture;
    terrainTextures[1] = sandTexture;
    terrainTextures[2] = grassTexture;
    terrainTextures[3] = rockTexture;
    //Paints the textures.
    kit.TextureTerrain(slopeStops, heightStops, terrainTextures);
    }

    public void Generate(bool doublePerlin) {
    //Generate the perlin terrain.
    kit.PerlinGenerator((int)Random.Range(3,6),Random.Range(0.4f,0.9f),Random.Range(2,6), 1f);
    //Gives it a less smooth feel.
    if(!doublePerlin){
    kit.PerlinGenerator(4,4,4, 0.1f);
    }
    //Creates arrays for stops.
    float[] slopeStops = new float[2];
    float[] heightStops = new float[4];
    Texture2D[] terrainTextures = new Texture2D[4];
    //Assigns values to the arrays.
    slopeStops[0] = 30f; slopeStops[1] = 70f;
    heightStops[0] = Random.Range(0.05f, 0.18f);
    heightStops[1] = Random.Range(0.19f, 0.49f);
    heightStops[2] = Random.Range(0.5f, 0.69f);
    heightStops[3] = Random.Range(0.7f, 0.89f);
    terrainTextures[0] = cliffTexture;
    terrainTextures[1] = sandTexture;
    terrainTextures[2] = grassTexture;
    terrainTextures[3] = rockTexture;
    //Paints the textures.
    kit.TextureTerrain(slopeStops, heightStops, terrainTextures);
    }

    }