Search Unity

instantiate, Grass, Trees , and rocks Based on the Terrain Textures

Discussion in 'Scripting' started by Rahd, May 21, 2018.

  1. Rahd

    Rahd

    Joined:
    May 30, 2014
    Posts:
    324
    So , i had this simple idea of using the terrain textures to pool grass and tress.. ect
    and use them over and over again . the goal is to have less draw calls and reuse the same prefabs to save cpu on mobile , since the game i'm making is for mobile .
    how it works :
    when i press trhe button it will call Grassmaker in the script attached.(to be changed to player movement event or loading screen) .



    the scrip will make a grid where the player is the center and will add 1 unit step till it reach the limit of the grid like 10 units (you can change this to have more details)
    then it will check the main texture used in the terrain once it has that it will check if the texutre name contains Grass or mud or rocks , or tree leafs ... ect
    and pick the prefab suited for the texture and instantiate it on the terrain in a random position around the sub grid cell center.

    so here is my script and i will be adding more soon , feel free to add your ideas . or if you know that some one have done this before so i can stop reinventing the wheel :). , and save time and effort .
    again this is a simple code , with little time put into it . i used foot steps terrain script as a start that i have found on github.

    *my next goal is to make the pooling system works , make multiple variations of Grass and trees rocks .. ect .. and change the size and rotation to make it feel natural.
    * Test the performance on multiple phones .

    My main problem is that i'm gonna use mesh terrain for my mobile game if any one knows how to pick up the used texture in a giving position without the terrain , i would be so happy .(let me know if you need the shader for the mesh terrain)
    Script :
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class NatureManager : MonoBehaviour {
    6.  
    7.  
    8.  
    9.     public Transform PlayerPos;
    10.     public Terrain terrain ;
    11.     public GameObject Grass;
    12.     public int GridXYlimit =10 ;
    13.  
    14.     public int SubGridXYlimit =1 ;
    15.  
    16.  
    17.  
    18.  
    19.     public void Grassmaker (){
    20.        
    21.  
    22.        
    23.         for ( int x = Mathf.RoundToInt(PlayerPos.position.x) - GridXYlimit ; x <= GridXYlimit +Mathf.RoundToInt(PlayerPos.position.x) ; x++) {
    24.            
    25.  
    26.             for ( int z = Mathf.RoundToInt(PlayerPos.position.z) - GridXYlimit ; z <= GridXYlimit+ Mathf.RoundToInt(PlayerPos.position.z)  ; z++) {
    27.                 Debug.Log (x);
    28.  
    29.                 Vector3 pos = new Vector3 (x, 0, z);
    30.  
    31.                 pos.y = terrain.SampleHeight(pos);
    32.  
    33.                 int index = GetMainTexture( pos) ;
    34.  
    35.  
    36.  
    37.  
    38.  
    39.  
    40.  
    41.                 Debug.Log (index);
    42.  
    43.                 if (    terrain.terrainData.splatPrototypes[ index].texture.name.Contains("Grass"))
    44.  
    45.  
    46.                 {
    47.                     int icount = 0;
    48.  
    49.  
    50.                     for (  int i = 0; i < SubGridXYlimit; i ++ )
    51.                     {
    52.                         var random = Random.insideUnitCircle  ;
    53.  
    54.  
    55.                         Vector3    Grasspos = new Vector3 (pos.x + random.x, pos.y , pos.z + random.y );
    56.  
    57.                         Grasspos .y = terrain.SampleHeight(Grasspos);
    58.  
    59.                         Instantiate(Grass, Grasspos, Quaternion.identity);
    60.                     }
    61.  
    62.  
    63.  
    64.  
    65.  
    66.  
    67.  
    68.  
    69.  
    70.  
    71.  
    72.  
    73.                 }
    74.  
    75.  
    76.  
    77.  
    78.  
    79.  
    80.  
    81.             }
    82.  
    83.  
    84.  
    85.  
    86.         }
    87.  
    88.  
    89.  
    90.  
    91.  
    92.  
    93.  
    94.  
    95.  
    96.     }
    97.  
    98.  
    99.  
    100.  
    101.  
    102.  
    103.     public   Vector2 GetTerrainPosition(Vector3 worldPos) {
    104.        
    105.         TerrainData terrainData = terrain.terrainData;
    106.         Vector3 terrainPos = terrain.transform.position;
    107.         int mapX = (int) (((worldPos.x - terrainPos.x) / terrainData.size.x) * terrainData.alphamapWidth);
    108.         int mapZ = (int) (((worldPos.z - terrainPos.z) / terrainData.size.z) * terrainData.alphamapHeight);
    109.         return new Vector2(mapX, mapZ);
    110.     }
    111.  
    112.     private   float[, ,] GetAlphaMapsForPosition(Vector3 worldPos, int size) {
    113.         // get the splat data for this cell as a 1x1xN 3d array (where N = number of textures)
    114.         TerrainData terrainData = terrain.terrainData;
    115.         Vector2 converted = GetTerrainPosition(worldPos);
    116.         return terrainData.GetAlphamaps((int) converted.x - size / 2, (int) converted.y - size / 2, size, size);
    117.     }
    118.  
    119.  
    120.     public    float[] GetTextureMix(Vector3 worldPos) {
    121.  
    122.         // returns an array containing the relative mix of textures
    123.         // on the main terrain at this world position.
    124.  
    125.         // The number of values in the array will equal the number
    126.         // of textures added to the terrain.
    127.  
    128.         float[, ,] splatmapData = GetAlphaMapsForPosition(worldPos, 1);
    129.  
    130.         // extract the 3D array data to a 1D array:
    131.         float[] cellMix = new float[splatmapData.GetUpperBound(2) + 1];
    132.         for (int n = 0; n < cellMix.Length; ++n) {
    133.             cellMix[n] = splatmapData[0, 0, n];
    134.         }
    135.  
    136.         return cellMix;
    137.     }
    138.  
    139.     public  int GetMainTexture(Vector3 worldPos) {
    140.  
    141.         // returns the zero-based index of the most dominant texture
    142.         // on the main terrain at this world position.
    143.  
    144.         float[] mix = GetTextureMix(worldPos);
    145.  
    146.  
    147.         float maxMix = 0;
    148.         int maxIndex = 0;
    149.  
    150.         // loop through each mix value and find the maximum
    151.         for (int n = 0; n < mix.Length; ++n) {
    152.             if (mix[n] > maxMix) {
    153.                 maxIndex = n;
    154.                 maxMix = mix[n];
    155.             }
    156.         }
    157.  
    158.         return maxIndex;
    159.  
    160.     }
    161.  
    162.  
    163.    
    164.  
    165. }
    166.  
     
  2. AnthonyMyers

    AnthonyMyers

    Joined:
    Jul 25, 2014
    Posts:
    28
    Hey Rahd that's something I was looking onto doing myself, there was a procedural generator on the asset store that was free for about a week. But I missed the download dead line.
    Hey I was wondering if you would sell some of your addons or maybe trade for assets made by me to your specs.
    Would be great if there was a sub forume for add on assets for sale on the store.
    Especially when the development of the said works, from the owner is not going where you want them.
    Not to pointing any fingers but melee for a certain asset not being developed after being ask for since day one of the forum post comes to mind
    Still a great asset but its getting a little frustrating when there going in a different direction.
     
  3. Rahd

    Rahd

    Joined:
    May 30, 2014
    Posts:
    324
    Sorry for the late reply , i'm using Cover shooter pluging and melee is now working and even better shotguns and alot more like zombies . the dev of cover shooter have added alot . check it out .