Terrain CPU Performance

Hi,

(Note I already posted this on the console-specific forums and was told this was a general problem)

We’re working on a project that makes use of a single terrain object in each level, and are seeing some alarming CPU performance problems on consoles. We’re currently main-thread bound on the CPU and are running 5.3.5p1 (though I see no difference running 5.4b)

Profiling the game on the consoles (using their profiling tools, not Unity’s), I notice that 25-35% of the main thread is spent in TerrainManager::CullAllTerrains, and later during rendering, there is a lot of time spent in QuadTreeRenderer’s destructor (which I assume is also terrain).

The fact that a lot of the profile hits are in data structure creation/destruction, this seems like an obvious target for optimization.

So my questions would be:

  • Are there plans in the near term to fix this?

  • What changes can we make that will reduce the CPU cost of the terrain without drastically affecting visual quality (this is a finished game).

  • Does anyone have experience converting terrain to use static meshes and traditional rendering? The geometry part is easy, but we would also need to manage/render all the details (trees/grass,etc).

This is currently a huge blocker on our project and is preventing us from hitting our target framerate, so any help is appreciated.

-Andy

Terrain is a performance hog, there’s no doubt. But that’s at least partly because it’s necessarily complex.

You haven’t provided much detail about your terrain settings, but the only easy way to improve CPU performance is by reducing the heightmap size or increasing the pixel error. These will both reduce the polygon count and also decrease draw calls. Although you’ve said you’re not GPU-bound, you should also look at the terrain shader - Unity’s default one is not that efficient IIRC. Is your terrain casting shadows? That’s another possible performance hit.

There are assets that will automatically convert from terrain to a mesh object, including retaining the position of grass and trees placed etc., but they too will necessarily reduce the quality of your terrain. Assuming you’re using the default 513 heightmap resolution, for example, that’s 262k vertices and over 500k triangles - far greater than would be allowed in a single mesh. Unity’s terrain has a built in LOD system that accounts for this by dynamically decreasing the resolution of the mesh further away from the camera, but a simple mesh solution would not be capable of doing this, so must simplify the entire mesh resolution.

You could also look into chunking your terrain into a number of smaller sections and stitching them together. Doing so might give you finer control over pixel resolution of distant terrain elements, and benefit from culling terrain chunks that are not visible.