How to optimize trees and bushes ?

I’m making a forest that I want to seem natural and for that reason I’m adding quite many trees,bushes etc.
I add the bushes using the Terrain Script that shows on the inspector window when I select the Terrain,and it uses a brush,not placing each tree individually.
The problem I come up to is that from what it seems there is a draw call for every bush or tree.
You can see how this can get things really bad if you are making a forest.
So while testing in play mode,the draw calls went up to 17.000+.
That made frame rate to go to numbers as low as 16fps.
And I haven’t even added lighting,animations,particles and AI yet! :o
Please tell me there is a way to make each individual bush become a part of the whole terrain so when the draw call for terrain is called all the bushes and trees are drawn on the same call.
I know that changing the draw distance could help,but this is in first person,and I want the player to be able to have an idea of what is far away,without having to get far away.

Ultimately there is a myriad of methods you can use to help lower the amount of draw calls when populating the scene with many pieces of sprayed on or even hand placed foliage. But be sure to keep in mind foremost that your terrain alone will generate draw calls depending on it’s complexity and there is some optimizing tools right in the terrain settings that will help you with that. Primarily regarding it’s detail distance.

In that same menu there is settings for the detail that might need a bit of tweaking on your part to get those calls lower with regard to all tools; plants, grasses and trees.

The draw distance can be set high and still get a good full scene at low calls if you understand how to deal with the billboarding and do your very best to limit the amount of objects while still filling up your scene.

Furthermore, adding in collision on each tree just adds to the mix and I believe there is a collision cap per scene to be mindful of.

Lastly, the plants, grass and trees themselves can all be optimized at the point of development. Some people prefer mesh limbs on a tree vs flat images but there are techniques that will help you figure some of that out in the Unity Wiki. In some cases you might use a mesh, in others you might use only an image, and in others you might use both.

Also look at forward rendering, batch and static rendering, and other optimizations that directly affect draw calls.

All in all it’s a lot of stuff to consider and unfortunately you may not understand how far you need to optimize until you get 17K draw calls so it might feel like working in reverse half the time, but as you learn about all these details you’ll be able to garner a better A-Z workflow and reduce these types of optimizations at the point of asset development.

Best of luck.

References:

Tree Creation Tutorial on Unity Wiki:
http://wiki.unity3d.com/index.php?title=TreeCreator_Tutorial

Draw Call Batching:

Occlusion Culling:

1 Like

As long as you use Unity’s built in terrain and vegetation system, you are going to be at the mercy of how it handles such. It’s a general purpose system, and seems to work pretty well for most projects.
But you want heavy, dense vegetation. To the best of my knowledge, there are only a couple of ways to reduce this:

  1. Draw less
  2. Draw detailed stuff close, and hide the distant stuff with fog, darkness, etc. Depends on your game.
  3. Batch it.

I think the first 2 are up to you, and don’t require any explanation here. The third option…

Batching is just combining multiple meshes into a larger mesh. The BIG limitation on this is, Unity has a 64k vertex limit for each mesh. So you won’t be able to create one giant honker mesh that contains terrain, trees, vegetation etc etc.

Terrain to me isn’t that big a deal…it’s not the big culprit in draw calls, because it is already sort of batched anyway. Granted, Unity’s terrain to me seems somewhat heavy on draw calls. You may end up wanting to go with your own terrain system.

So now you are looking at batching plants and grass. I would highly recommend separating them into two different batching processes, instead of having grass and plants all combined in the same mesh.

Grass is somewhat simpler, it’s normally just a grass quad with the grass texture on both sides. 8 vertices, 8 normals, 4 triangles. Add them to your new mesh that holds all of the batched grass for an area.

Plants…in my case, I took the raw plant mesh, baked in a rotate/scale (at runtime) and added it and its vertices, normals etc to the plant batch/mesh. Check out :

This allows you to take a mesh, and “bake” in the transform, rotation and scale. This allows you to have plants or whatever, rotate/scale them, and still combine them into a batched mesh.

The vertex count limit will dictate how many “grasses” or plants you can add to each batch before starting a new one. And something to consider…you don’t want a batched mesh to be a long strip across your terrain. What I mean is…let’s say your plants can have a max of 1k vertices each. This sounds like a lot, but you can burn through that EASY. Anyway, if you set a max vertex count of 1k for each type of plant mesh, this means you can have 64 of these all batched together.
So your batching code…the easiest way is just to start adding plants until you would bust through that 64k vertex count, then start another batch mesh for them. But geographically, this could end up in a mesh that covers a long strip of plants from your terrain. This is not efficient for visibility culling at all. Granted, it’s a great draw call reducer, but it’s best to do like an 8x8 grid of plants instead of a 64x1 strip of plants. But the code is more complex to have a really efficient batch in that case. Just adding a plant as long as it falls under the 64k count is easier. Targeting an 8x8 area may only be half full of plants, which means you either have 32k vertices (half full) and thus a less effecient mesh. It just gets messy, and ultimately…may not be that big a deal either way. I chose to target a square region of plants to batch, instead of packing as many as I can in a 64k mesh. Honestly…I think the big hit on may graphics cards today is FILL RATE, NOT how many vertices are loaded. Yeah you could go crazy with super detailed plants, but from reasonable low poly stuff, fill rate seems to be the killer.

Anyway…if you had 64k plants, if you tried to draw each one that’s 64k draw calls. If you batched them all you would have 1k draw calls. Massive reduction. 64k sounds like a lot…but it’s really not in a dense forest. You are talking about a 256x256 square area…again depending on how your game works.

I know Unity has static and dynamic batching, but honestly there seem to be too many restrictions. Can’t rotate them. No scale changes. . Less than 300 vertices…I guess you could fit a cabbage or…some super simple plant in that.

Couple of other things…if you batch your meshes, you lose the built in wind stuff. That means you’ll need to find a shader that handles this for you (see Lars bertram’s shaders). This means that for each mesh, you’ll need to go in your modelling program and color the vertices of the mesh. Wheeeee. Lars has an editor tool to color the meshes, but it may not work well for all types of vegetation. He may be able to shed more light on this.

Trees…honestly, it’s up to you but I personally don’t combine trees, but that’s because in my project I am already batching grass into mesh patches, plants into their own mesh patches, and the drawcall count is pretty darn low. I just haven’t seen my fps drop enough to worry about it.

Also, it’s easier if your world is static. If you want a world where you can change terrain and trees and such…it gets more challenging.

And did I mention, if you use your own custom vegetation system…you’re going to have to either use Unity’s vegetation painting system somehow to create your world and place your vegetation, or make your own. I would recommending using Unity’s as much as you can, maybe like this:

Create your initial terrain, call it “trees and grass”. This only stores tree information and grass information.
Create another terrain, and import the same heightmap (do not duplicate the terrain using Unity, it shares the data which is bad). Or at least it did last time I checked. Call this one “plants”.

So on the plants one, add your plants as trees and paint them. On the trees and grass terrain, paint your trees and grass. Separate them so that you can use plants as trees for one, and trees as trees on another. I guess you could use one terrain for both…but you would have to add a custom editor to be able to specify which thing was a tree, and which was a plant. Up to you, I’d rather just separate them to make it less messy.
There, now you can paint and save this data using Unity, and your own vegetation system can read the data and handle it. Granted, it won’t give you control over painting rotation, but do you really have to specify rotation when painting, or can you just choose a rotation when you create your trees from the data?

Anyway…hope this helps. I really enjoy this stuff, hope I didn’t talk your ear off!

5 Likes