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

Creating a level with thousands of trees

Discussion in 'Scripting' started by knobblez, Aug 9, 2019.

  1. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    I made a game that's pretty simple. It's a single, very long road. It has trees along both sides and adds up to close to 5,000 trees. I'd like to extend the road which means I have to add more trees but it's already pretty slow due to all the tree objects.

    What is a recommended way of dealing with this? I was under the impression that my game wouldn't be this slow because I made my Far Clipping Plane 75, but it's still slow to load/run. Is this something that won't happen if I compile?

    **I'd like to build this as WebGL


    *EDIT well, compiling says ETA 6 hours so I definitely have to figure something else out...lol
     
    Last edited: Aug 10, 2019
  2. ismaelflorit

    ismaelflorit

    Joined:
    Apr 16, 2019
    Posts:
    38
    Have your considered creating them procedurally so that there are only ever the needed amount around the camera?
     
    SparrowGS likes this.
  3. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    I did consider that. The player is always moving forward so it would constantly be removing and creating trees. I figured this would definitely make the game slow. Maybe not this slow though. It'd probably end up being 10-20 trees being created/deleted every couple seconds.
     
  4. ismaelflorit

    ismaelflorit

    Joined:
    Apr 16, 2019
    Posts:
    38
    Last edited: Aug 10, 2019
    AdamsWalace likes this.
  5. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,606
    Loading (and rendering) thousands of gameobjects is really slow. As @ismaelflorit said you should definitely try creating trees only where needed. However, you can go a step further. As you said, constantly creating new gameobjects can be a bit taxing. Even worse, however, is constantly destroying gameobjects. This potentially causes a lot of garbage and thus spikes whenever the garbage collector runs. A common tactic to prevent this is object pooling (you'll find plenty of tutorials, here a short explanation).
    Try roughly figuring out how many trees you need at most in one screen and maybe take a couple more to make sure. Let's say you need, for example, 200 trees max at one moment in time. When the game first loads, instantiate all 200 trees and deactivate them. Add them to a list of pooled tree objects. Now, whenever you need to spawn a tree you dont have to instantiate a new one, you simply take one from your list of pooled trees, change its position and activate it. Vice versa, when you dont need a tree anymore (it left camera view) deactivate it again and add it to the list of pooled trees. No instantiation, no destroying, no garbage collection, lower loading times and the least amount of objects to render since you only spawn/show trees in camera view.

    Edit: Forgot to mention one thing. On top of only showing trees that lie within your camera view, you could also use something called Occlusion Culling to only show trees that are (on top of that) not hidden behind other trees: https://docs.unity3d.com/Manual/OcclusionCulling.html


    You may also want to take a look at the new DOTS architecture (ECS, Jobs, Burst) unity offers, since it results in highly efficient code, but i'm not sure it would perform any better than the above in this example, and also getting used to DOTS can take quite some time since it`s not even object oriented programming anymore.
     
    Last edited: Aug 10, 2019
    ismaelflorit, knobblez and Lethn like this.
  6. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    The marching cubes algorithm might be appropriate here but you could make something simpler and just have the trees spawn randomly.

     
  7. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,606
    Are you sure you wanted to refer him to marching cubes and not, say, poisson disc sampling? I fail to see how marching cubes would help him manage his trees better to be honest.
     
  8. Well, these are things where I usually use external assets. I'm too lazy to fight over these battles myself.

    If you don't want to do it yourself and you're willing to pay for a solution I can recommend the Vegetation Studio. Before you buy, please make sure it works for you (WebGL, I don't work in WebGL, so have no clue if it works or not).

    Other thing you can consider is GPU instancing.

    And an advanced impostor system, if you want to do it yourself at least a little bit: https://assetstore.unity.com/packages/tools/utilities/amplify-impostors-beta-119877
    So you can have advanced billboards.

    It depends if you want to have individual tree game objects or not, do you want to interact with them or not? Etc.
     
  9. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    Oh! I honestly didn't know about that, that looks like a much better option for sure, it's just the one that immediately sprung to mind because he mentioned he was using a road and Sebastian League used a submarine and procedural caves with his example.



    Might look this up myself.
     
  10. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,606
    The marching cubes algorithm is used to poligonize a scalar field, like the result of a mri scan in medicine, which is why it can be used to render procedural 3d terrain, including overhangs and caves. As i said, i doubt it's applicable here at all (unless OP suddenly wants to generate procedural mesh-trees) and since it's a quite complicated algorithm to grasp, i'd be a bit more careful where i posted it on a whim hehe :)
    Also, it's probably best if you edit your post to delete the marching cubes reference video so it doesnt end up confusing.

    Since you linked a video to Poisson Disc Sampling i guess i'll give a rough explanation why that might be of interrest for OP: it's an algorithm used to determine where you can place objects with a given radius, so that they are semi-random but cannot clip/ overlap. Unless you want to manually create a list of coordinates for where your 5000 trees should be placed, you could use this to find spots for your trees to be placed at. If you want the identical scene you manually crafted tho, i guess you will have to read out the positon of all the trees you placed and put them into a lookup list of desired coordinates (on which you spawn a tree if it's inside the camera view like mentioned above)
     
    Lethn likes this.
  11. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    So, considering there are only 4 (let's call them columns) of trees running along each side of the road, I'm thinking it would be best to use this pooling method. I really appreciate all of the replies from you peeps.

    Here is a screenshot of my map in-case y'all have any further suggestions:


     
  12. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Let me just say that this is one hell of a thread. Good poisson disk sampling and marching cube tutorials within the span of four posts. The information density here is approaching stupendous!

    Thanks for the links :)
     
  13. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,606
    The image is really small, is that 2D? Either way it doesnt look to graphics intense from what i can see, so the main problem will definitely be the sheer amount of gameobjects (draw- and update calls and so on). Pooling and reusing objects should most certainly fix your performance problems. You also wont need poisson disc sampling, since you can just prefedine the distance between trees and place them on your predefined "columns", if that's what you want.
     
  14. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    Got it working!

    From 5000 trees to 100 trees. It's running much smoother now :p.

    I ended up creating 8 "column" objects and 8 "spawner" objects. The columns are a child of the player and the spawners stand alone. The spawners line-up with the columns but are placed ahead. When the columns collide with the spawners, it triggers OnTriggerEnter and activates a tree at the position of each spawner, it also adds Random.Range(4.5f, 8f) to the Z axis of the spawners which moves them ahead again. I also added a random rotation to the trees when they are initially instantiated. This kept it organized(off the road) but appearing scattered.

    @Yoreki This is a 3D game

    Here is a pic for those that are interested in what I did:
    Spawners are yellow, columns are pink. Columns move forward(only forward) with Player


    Thanks again for all the help! :D
     
    Last edited: Aug 11, 2019
    Lethn and Yoreki like this.