Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Random Object Instantiation and Terrain Height

Discussion in 'Prefabs' started by omnivore, Jan 31, 2023.

  1. omnivore

    omnivore

    Joined:
    Sep 11, 2014
    Posts:
    3
    hello!

    My code is working well to distribute my cacti over X and Z.

    However, Terrain.activeTerrain.SampleHeight seems to be ignored, and my cacti are not displaced along with the terrain in scene.

    Any advice on how I can fix up my code would be hugely appreciated.
    cheers

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SpawnTogether : MonoBehaviour
    6. {
    7.     public GameObject[] myObjects;
    8.     public int cactusNumber;
    9.    
    10.  
    11.     void Start()
    12.     {
    13.         CreateCacti(cactusNumber);
    14.     }
    15.  
    16.     void CreateCacti(int cactiNum)
    17.     {
    18.         for (int i = 0; i < cactiNum; i++)
    19.         {
    20.             int randomIndex = Random.Range(0, myObjects.Length);
    21.  
    22.             Vector3 pos = transform.position;
    23.             pos.y = Terrain.activeTerrain.SampleHeight(transform.position);
    24.             pos.x = Random.Range(-110, 110);
    25.             pos.z = Random.Range(-580, 580);
    26.  
    27.             Instantiate(myObjects[randomIndex], pos, Quaternion.identity);
    28.         }
    29.     }
    30. }
    31.  
     
  2. LethalGenes

    LethalGenes

    Joined:
    Jan 31, 2023
    Posts:
    69
    Try getting and then setting.
    Such
    var the result of terrain active terrain sample height and then set the .y to this variable.


    If all else fails
    Debug log your active terrain
     
  3. omnivore

    omnivore

    Joined:
    Sep 11, 2014
    Posts:
    3
    Is this was what you meant @LethalGenes ?
    It made sense but I'm a coding pleb and this still isn't working as expected.

    I'm hoping I've just made some really obvious mistake:


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SpawnTogether : MonoBehaviour
    6. {
    7.     public GameObject[] myObjects;
    8.     public int cactusNumber;
    9.    
    10.  
    11.     void Start()
    12.     {
    13.         CreateCacti(cactusNumber);
    14.     }
    15.  
    16.     void CreateCacti(int cactiNum)
    17.     {
    18.         for (int i = 0; i < cactiNum; i++)
    19.         {
    20.             int randomIndex = Random.Range(0, myObjects.Length);
    21.  
    22.             var spotHeight = new Vector3(i,Terrain.activeTerrain.SampleHeight(transform.position),i);
    23.  
    24.             Vector3 pos = transform.position;
    25.             pos.y = spotHeight.y;
    26.             pos.x = Random.Range(-110, 110);
    27.             pos.z = Random.Range(-580, 580);
    28.  
    29.             Instantiate(myObjects[randomIndex], pos, Quaternion.identity);
    30.         }
    31.     }
    32. }
    33.  
     
  4. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    595
    You are always sampling the height at the same position(transform.position) for all cacti. What you probably wanted is sampling the height at the position where you are going spawn current cactus. Which means that you need to reorder things a bit:
    * choose random x, z values
    * sample height at chosen x, z position
    * create spawn position using the previously generated random x,z and height sampling result
     
  5. LethalGenes

    LethalGenes

    Joined:
    Jan 31, 2023
    Posts:
    69
    Sorry I meant

    Code (CSharp):
    1. float P = Terrain.activeTerrain.SampleHeight(transform.position);
    Then you should apply that P instead of setting a get function. Sometimes you can set a get function absolutely fine but other times it can not work. So it’s best to get the float that you need before setting. Terrain.activeterrain sample of transform position is a long get request on the same line as a set request.
     
    omnivore likes this.
  6. omnivore

    omnivore

    Joined:
    Sep 11, 2014
    Posts:
    3
    yes, success.
    thanks so much for taking the time to reply @karliss_coldwild and @LethalGenes
    I'll put my working code here for future noobs like myself


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SpawnTogether : MonoBehaviour
    6. {
    7.     public GameObject[] myObjects;
    8.     public int cactusNumber;
    9.    
    10.  
    11.     void Start()
    12.     {
    13.         CreateCacti(cactusNumber);
    14.     }
    15.  
    16.     void CreateCacti(int cactiNum)
    17.     {
    18.         for (int i = 0; i < cactiNum; i++)
    19.         {
    20.             int randomIndex = Random.Range(0, myObjects.Length);
    21.  
    22.             Vector3 randomSpawnPosition = new Vector3(Random.Range(-110, 110), i, Random.Range(-100, 110));
    23.  
    24.             float spotHeight = Terrain.activeTerrain.SampleHeight(randomSpawnPosition);
    25.  
    26.             Vector3 pos = transform.position;
    27.             pos.y = spotHeight;
    28.             pos.x = randomSpawnPosition.x;
    29.             pos.z = randomSpawnPosition.z;
    30.  
    31.             Instantiate(myObjects[randomIndex], pos, Quaternion.identity);
    32.         }
    33.     }
    34. }
    35.  
     
    LethalGenes likes this.