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
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.
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: Unity - Manual: Occlusion culling
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.
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.
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).
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.
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)
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:
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!
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.
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.