Poor performance with many procedurally generated terrain blocks.

I am getting very poor performance when using a lot of smaller terrain blocks to piece together a larger map (they’re never actually connected and remain separate).

I’ve found the 10 x 10 grid maps to be a good size for my game. Each grid section is further dissected into 9 10x10 meter terrain chunks. 9x10x10 = 900 Unity objects much be instantiated for this to work. This ends up causing major lag, and also crashed my computer at one point. The whole operating system froze for about 15 or more seconds until the map loaded. The game was unplayable after loading in (no surprise).

I then tried using larger chunks of terrain of size 50x50 meters. This gave acceptable performance (on my gaming machine at least) at the 10 x 10, but much higher and unbearable lag starts to show up.

I was thinking of pooling assets and disabling / reusing them as the character becomes closer to them, but when testing if performance became better when disabling objects, it did not. It seemed as if Unity was still lagging horribly from the objects even though they are disabled.

Since the map is in a Diablo style view, I can’t imagine that it’s overdraw that’s causing this, since the camera is angled downwards (not completely down, but from an angle).

Any ideas on how I can go about making these larger, procedurally generated areas without getting major lag? Is it just the terrain objects that are causing issues, and I should manually create the meshes for each block of land?

A lot of objects will kill the performance (lots draw calls). You could look in to merging the meshes if possible!

There are actually only about 200-400 draw calls being made. The objects are not causing extra draw calls since they are off the camera view. This is also for PC, so draw calls at the current rate shouldn’t be an issue.

It’s not entirely clear from your post if you are saying that it takes a long time to load/spawn/instantiate all your blocks, or if your game is running slow after instantiation. Because if it is the former, then just put up a load screen.

I am doing a flat top-down world with 16384 tiles total, with about 200 visible at a time, and I don’t have any slow down at all. However my tiles are just quads with a simple shader. Still I would expect a modern PC to be able to handle 200-400 objects in a scene. Could there be something else slowing it down? Like maybe some script attached to every object that is slower than you thought it would be?

Well using one mesh for larger chunks in a voxel engine for unity i am working on helped performance a lot.

By "The game was unplayable after loading in " I meant that there is a huge drop in frame rate after the initial load that does no go away even after disabling almost all gameobjects in the scene.

Are you using occlusion culling for this? Do you disable tiles that are not seen, or do you just instantiate them and leave them?

I am thinking that it has to do with the terrain objects (unity’s default terrain objects). Since I really have no use for almost any of the terrain’s features (other than the moving trees and grass and painting tools) I am going to attempt to just make my own meshes externally and see how it goes.

After testing more with this, it’s seeming like unity just handles large amounts of game objects poorly, even if they are static.

I’m getting pretty worried about how to handle what I wanted the general concept of my game to be like (large, procedurally generated dungeons). I guess the only answer is to keep each scene pretty small.

No I am definitely not doing any manual occlusion culling. I don’t think I need to do that for an object with no scripts on it. I instantiate them and leave them. They are just sitting there waiting to be rendered if they ever clip into the camera frustum.

In my normal view, my stats show “Draw Calls 135 batched: 578”. Running at 3.5ms unsynced.

If I zoom the camera all the way out, which would never happen in normal gameplay, my stats show “Draw Calls: 701 batched: 16734”. Running around 40ms.

Now if they had scripts on them, then I would disable them when they were far enough away from the player, but that is not the case for my ground tiles. I should also add that this is a turn-based game so there is almost nothing going in while it is idling except drawing a bunch of simple tile objects.

I would expect that you would get far greater performance with static meshes than the built-in terrain system, though that is based on my experience with other engines in the past. I have not tried Unity’s terrain.

hi
@Disastercake few months ago I also face the same problem, my draw calls at some level goes over 6000 and more :smile: I than tried few thing, that people mention in forums. Like disabling gameObject that are not in players view, but nothing helps. I still don’t know the correct reason.
If someone know anything please share…

The draw calls are definitely not the issue for me (they remain in the couple hundred only). Also, if you are using a single huge terrain, and your camera view is more like a FPS, then you’ll be getting a lot of overdraw. you cant manually disable things like trees. Have you tried occlusion culling that comes with unity pro? I can’t use that because my scenes are randomly generated.

Do you by chance have any colliders on those objects?

The original terrain has it’s collider attached to it. I didn’t consider that the default terrain may be an expensive calculation, and since I am using completely even terrain, I will try changing that.

When I tested with the boxes and planes, however, they all had their default plane and box colliders. However, they didn’t have rigid bodies attached, and those should be pretty simple collider calculations for just sitting there.

I would say the weirdest part about this is that the profiler is literally useless. Nothing is coming up with more than like 2-4 MS.

I’m not certain this will be helpful to you but on my procedurally generated terrain I’ve found that the heightmap resolution is the primary determinant on dumping your fps.

As an example, on a single block of terrain, I have a 1024X1024 terrain, scaled to 2048x2048 length and width with a good framerate. This is done at run time and with the pixel error set to 0 so no LOD is employed.( The camera view is from overhead so I can fit the entire terrain in one frame). To add to that, I’m using a projector to place grid lines and some visual debugging information which doubles the draw calls.(I’m in the 4 to 5 thousands of draw calls usually). This runs at a consistent mid 90 frames per second.

On the other hand when I try to generate a single resolution of 2048 X 2048 my screen turns into a slide show and I sometimes have to kill the application from the shell to regain control. All of this from a total of 2 game objects.

Something to test would be to push your terrain to a more code-centric approach and have it touch the component system a bit less.