BenchMark 1. Product Shelf

This test is a product shelf, full of products. Each product is a separate mesh. The blueprint itself is comprised of 128 meshes. The test was performed on an i7 12K 64GB, 8GB 3070ti in UE5.2.1. All meshes are Nanite.

This is repeated 200 times in the level. The shelf and contents combine to 128 meshes, so 25,600 meshes.

1. Plain Actors

The above snapshot is showing the default, non-instanced version – the playback rate is not too bad considering, at 78-80FPS – but that’s not really that many objects.

Editing it and loading/saving is very tedious, waiting 10-100 seconds for some operations. Playing takes over 10 seconds, if things have changed a lot it can take minutes. UE5.2.1 crashes while saving often too.

Timings:

Render: 12.72 milliseconds (78.6 FPS)
Dup10: 8.45 seconds
Load: 93.75 seconds
Save: 6.11 seconds
Play: 11.43 seconds

Ratings:

Rendering: 3/5
Editing: 1/5
Playing: 2/5
Variety: 1/5 (potential to add variety with custom blueprints/c++))
Interact: 1/5 (potential to add interaction with custom blueprints/c++)

Average: 1.6/5

Conclusion: Very painful, and not the optimal – unstable.


2. Prefab Created with default “Convert Selection to Blueprint Class” tool

The next test is with a Prefab created with the default tool built into Unreal:

This creates a ChildActorComponent for each product and each shelf. The Static meshes are not instanced in any way.

Editing these is even more painful – incredibly slow to duplicate and move multiple prefabs at once. In fact I’ve written this whole paragraph, gone back into UE to see if it’s finished duplicating 20 of them – and it’s still processing…

It’s just too slow, I wasn’t able to recreate the testing using this method.

Note that even with just 76 shelves the framerate has already dropped to below 100FPS – they are not fast to render.

Timings:

Render: extrapolating, around ~14 milliseconds (~80 FPS)
Dup10: 18.2 seconds
Load: 8.8 seconds – extrapolating full amount, around 23.14 seconds
Save: 4.65 seconds – extrapolating full amount, around 12.23 seconds
Play: 5.01 seconds – extrapolating full amount, around 13.18 seconds

Ratings:

Rendering: 3/5
Editing: 0/5
Playing: 3/5
Variety: 1/5 (potential to add variety with custom blueprints/c++)
Interact: 1/5 (potential to add interaction with custom blueprints/c++)

Average: 1.6/5

Conclusion: Unusabletoo many components!


3. Instanced using the MergeActors Instancing tool

This test instances all the actors from the first test using the MergeActors instancing tool:

Creating the actors ready to convert is very painful, like the first test – and the conversion is very slow too. Once they are converted though, editing is faster and rendering is faster.

Timings:

Render: 9.51 milliseconds (105.16 FPS)
Dup10: 0.91 seconds
Load: 2.76 seconds
Save: 1.56 seconds
Play: 2.25 seconds

Ratings:

Rendering: 4/5
Editing: 3/5
Playing: 4/5
Variety: 1/5 (potential to add variety with custom blueprints/c++)
Interact: 1/5 (potential to add interaction with custom blueprints/c++)

Average: 2.6/5

Conclusion: It’s just as painful to create and edit the actors as the first test, so has limited use. The Instancing system used is not the most efficient.


4. Merged Single Mesh per shelf, Instanced

The next test is merging all the products and shelves into one static mesh. The mesh still references the original materials, so there is a draw call for each one. Then the shelves are laid out in the same manner as the last tests, 20×10 grid spanning from close to the camera to far.

As each Shelf is a complete mesh, they are all drawn with no culling, so the rendering speed isn’t as performant as it can be. Note that complex collision on complex meshes doesn’t come for free either.

Timings:

Render: 8.66 milliseconds (115.45 FPS)
Dup10: 0.14 seconds
Load: 2.87 seconds
Save: 0.34 seconds
Play: 1.2 seconds

Ratings:

Rendering: 4/5
Editing: 5/5
Playing: 5/5
Variety: 0/5 (cannot introduce variety into a static mesh)
Interact: 0/5 (cannot interact with individual components of a static mesh (easily))

Average: 2.8/5

Conclusion: Merged static meshes can give the impression they are very efficient. By themselves they are – but as soon as you want any variety (eg, different products taken from shelves) you have to create many different merged meshes, and either multiple materials per mesh (multiple draw calls) or a selection of materials – all taking a lot of VRAM.


5. Merged into a PackedLevelActor

This test creates a PackedLevelActor of the shelf and uses that. It gets good rendering speeds and is nice to edit.

Timings:

Render: 8.98 milliseconds (111.32 FPS)
Dup10: 1.41 seconds
Load: 2.81 seconds
Save: 2.23 seconds
Play: 3.22 seconds

Ratings:

Rendering: 5/5
Editing: 4/5
Playing: 4/5
Variety: 1/5 (potential to add variety with custom blueprints/c++)
Interact: 1/5 (potential to add interaction with custom blueprints/c++)

Average: 3/5


6. Prefab created with rdBPtools and default instancing

This test uses the default instancing system built into rdBPtools prefabs. It’s not the most efficient as it creates Instance Handlers for each Blueprint you create, but they do behave with World Partitions.

The editing did start to slow down a little with quite a few in the level, but was still usable.

Timings:

Render: 9.11 milliseconds (109.74 FPS)
Dup10: 1.09 seconds
Load: 5.05 seconds
Save: 0.88 seconds
Play: 3.65 seconds

Ratings:

Rendering: 5/5
Editing: 4/5
Playing: 5/5
Variety: 5/5 (randomization build into rdBPtools Prefab classes)
Interact: 1/5 (potential to add interaction with custom blueprints/c++)

Average: 4/5


7. Prefab created with rdBPtools and rdInst instancing

The final test is with rdInst as the instance handler. This option gives the best results by far – both in rendering, and in the editing experience. The editor didn’t slow down at all handling all the instances.

Timings:

Render: 8.33 milliseconds (120.02 FPS) (Note: the frame-rate is capped at 120, so is being rendered faster)
Dup10: 0.37 seconds
Load: 1.02 seconds
Save: 0.90 seconds
Play: 1.14 seconds

Ratings:

Rendering: 5/5
Editing: 5/5
Playing: 5/5
Variety: 5/5 (Randomization built into rdInst – fast c++)
Interact: 5/5 (rdInst has tools to convert instances to actors (and actor pooling) and back to instances)

Average: 5/5