Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Spawn mountain prefabs based on noise map

Discussion in 'Scripting' started by dontzaponenn, Apr 1, 2024.

  1. dontzaponenn

    dontzaponenn

    Joined:
    Dec 15, 2022
    Posts:
    5
    Hi,
    I created a noiseMap with a falloff ( to look like an island) and with some elevations. I have multiple biomes on different heights : water, sand, grass, mountain, ice . Instead of these mesh generated elevations, i want to achieve this:
    I created some prefabs that look like mountains, and when the values in the noiseMap vector are like >0.8 i want to spawn these mountains. I've created the code to not the overlap these prefabs based on the radius of each prefab (calculated based on the mesh size). My issue now is that a prefab has a size. If i find a value of the noiseMap which is >0.8 i spawn this object but considering the fact that this prefab has a bigger size than the 1 vector position, the prefab will go for example in the water or over the sand.

    Which will be the best approach to spawn these prefabs?
    I was thinking about checking the edge of each prefab and basically map these size values into the noise map in a for loop (looping through the noiseMap values). But for sure, this will take around 20 years to spawn.

    If more info is needed, let me know. i can provide code snippets as well.

    In the attached screenshot you can see that the prefab is over the water and sand. Exclude the fact that i have mountains procedural generated, i want to get rid of these
    Thank you !
     

    Attached Files:

    • egg.png
      egg.png
      File size:
      1.9 MB
      Views:
      14
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,535
    One way would be to have spawned mountains affect the terrain surrounding them, eg replacing any water terrain around a mountain. This however can still lead to all sorts of visual and gameplay issues.

    The better alternative is to assume everything is on a grid, including the terrain. That doesn't mean the terrain has to look blocky (research: wang tiles).

    Or you could experiment with a heat map approach. Rather than spawning a mountain for the first >0.8 entry you find, you would instead rate whole areas based on how much >0.8 is surrounding them. Then only spawn a mountain for places where the average value of surrounding height values is >0.8. That way you don't spawn a mountain right on a steep cliff but always where more high terrain is surrounding the mountain.
     
  3. dontzaponenn

    dontzaponenn

    Joined:
    Dec 15, 2022
    Posts:
    5

    Can you suggest an approach to get this heat map? Like if i want to check the surrounding points in a for loop that will end in a memory leak i suppose. It should be a solution to map the size of the prefab footprint on the noiseMap to see the "surroundings" in the noiseMap values without looping through all of the noiseMap values. I guess System.Linq is not a solution.
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,535
    You mean index out of bounds? Safeguard against those of course. But nothing in that inherently spells "memory leak".

    No, definitely not. I'm thinking this gets parallelized with a job. I mean it's just numbers (value types) so it'll perfectly scale up to be several hundred times faster than your current LINQ implementation with a bursted parallel job.

    Search for "heat map algorithm". There are many approaches but in its simplest form you take one value in the array (I assume its a 2d map) and then sum and average the surrounding values, for a rectangular area pseudocode is: avg(x±n + y±n) where n is the size of the rectangle (1 or higher).

    A clever trick to avoid index out of bounds and the necessary checks would be to pad the 2d map with n zero values in all four directions but iterate only over the actual map data. Conditionals typically break vectorizatio, but vectorization is where you get the "several 100s" speed-up factor from due to compounded effect of vector operation doing 8+ times the work in a single operation plus avoiding cache misses.
     
  5. dontzaponenn

    dontzaponenn

    Joined:
    Dec 15, 2022
    Posts:
    5
    Sorry but i don't understand why a heat map will help me. What should i check after i generate this heat map? If the area is green or red or whatever? I can check directly the value in the noisemap
     
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,535
    If I understood correctly, you go over the noise map. The moment you find a >0.8 value you spawn a mountain there. But that means, assuming you walk the array top to bottom, left to right, that to the top-left of the mountain is terrain that is less than 0.8 height (let's call that a cliff edge).

    If you do a heatmap, or essentially averaging each map point based on its surrounding values, you can guarantee that the first >0.8 value will not be at a cliff edge but deeper inside the mountainous area. Otoh there may no longer be a mountain where you previously had one because there were only very few >0.8 at that location.