My colleague provided additional helpful details:
Does each (Nanite) landscape component increases UObject memory footprint and the size of the physics scene by inflating the AABB tree enough to be a concern?
There’s usually 1 Nanite landscape component per ALandscapeStreamingProxy so UObject memory footprint should be of little to no concern. There’s 1 such component for every 64 landscape components in a given ALandscapeStreamingProxy because 1 Nanite component holds exactly 1 static mesh, which can only own up to 64 mesh sections and we have one mesh section per landscape component, in order to assign the component’s material instance to the corresponding mesh section. Above 64 landscape components per proxy, another Nanite landscape component gets created to host the next 64 and so on.
This is purely a visual component so there’s no impact on physics or navigation. No distance field or Lumen card data either : standard landscape is still around so all of these are handled by it.
Are there any other places where we will feel the impact of having too many (Nanite) landscape components in our scenes?
If Nanite rasterization costs are too high, you should increase the size of your landscape components to minimize it and fit in your budget. Shader bundles on PC may help here, but in our testing, it primarily helps on lower end hardware.
What would be a max adequate landscape component size? Where would we see the impact if we were to go over this size?
The maximum resolution per component is 511x511 (255x255 quads + 2x2 subsections). Then landscape can be scaled as needed in order to maintain the desired vertex ratio per world unit.
Larger components have the benefit of minimizing the amount of landscape MICs, which limits the amount of draw calls for standard landscape and raster bins for Nanite landscape.
But it also increases the potential for more expensive materials, since landscape target layer usage will likely become higher which is a consequence of the landscape components being less granular. When using RUntime Virtual Textures (RVT), this cost is amortized since it will mostly affect RVT page rendering, which happens over the course of multiple frames, only when new pages are needed and on a limited render area.
There is no component count limit on a given landscape streaming proxy, so it’s up to you to find the balance. Larger landscape streaming proxies have the following benefits :
- Tends to minimizes the cost of streaming (i.e. a lower actor streaming granularity means larger amount of data to stream at once but at a lesser frequency).
- Allows to minimize the amount of Nanite landscape components, although this is usually of little importance, since what matters for Nanite is the amount of mesh sections (see above).
On the other hand, they have the following drawbacks :
- All the CPU-resident data (landscape grass, if not using runtime grass generation, landscape collision, navigation data, Lumen cards, distance field data) will remain resident for longer, until the landscape proxy is replaced by HLOD
- Workflow-wise, minimizes the potential for concurrent work. Landscape streaming proxy size is identical in-editor and in-game. In other words, since an artist works at the actor level, the streaming proxy granularity is what defines how artists will be able to work on different sections of the world at the same time
Some licensees, use smaller sizes allow multiple artists to work simultaneously, even using a single component per ALandscapeStreamingProxy. This means you end up with a single Nanite landscape component per proxy too. But if it’s in your budget it allows you to keep the actor streaming granularity low, and you can rely on HLOD in the distance to minimize system memory.
On Fortnite, we use on 4 components per proxy and we don’t use HLOD at all (landscape is non-spatially loaded).
Another thing to remember is that most the heavier landscape data (heightmaps/weightmaps/Nanite landscape mesh data) is already streamable and they participate to their respective shared video memory pool so there’s automatic balancing happening there. If memory/streaming is a concern, we recommend looking into using HLOD and reducing your landscape streaming actor granularity in order to save on collision, navmesh, landscape grass data, etc.
Runtime grass can be saved altogether by activating grass.GrassMap.UseRuntimeGeneration 1 which will cause it to be rendered at runtime as needed and only a minimal amount kept resident.
[Attachment Removed]