Ideas on weapon optimization

As the title suggests. To sum up what I’m trying to do, you can think of Escape From Tarov. Lets take an M4 in that game. You can change out the barrel, muzzle device, rail/handguard, pistol grip, stock, buffer tube, receivers, charging handles, darn near everything. Whats an efficient way to go about doing this to where I can easily change out different parts of the gun (I’m not talking about programmatically) without having a bunch of draw calls for each gun? I want to be able to swap out kind of whatever part that I want which would mean a material instance for each mesh. So if I make the gun out of lets say the barrel, muzzle device, handguard, upper receiver, stock, pistol grip, and charging handle, thats 8 draw calls for the mesh and 8 for the materials. How can this be optimized? I know about welding meshes together, but that still me leave the issue of the materials.

Good question! I’ll be in the same boat eventually and have only given marginal thought to the issue. Material Instances and Instance Static Mesh Components where part of my “look in to” thought process. If I spawn an ISMC Actor (BP) for each type of attachment I can add/remove instances as needed. Haven’t tested it, but the general idea was If I attached the instance to the weapon mesh which is attached to actor it should stay with the character. 10 or 10,000 instances …1 draw call. Was thinking about the same process for map geometry as well. Prefab instances (HISM for lod support) etc.

Extremely interested in others ideas.

This Mesh Merge Plugin might help:) Otherwise, optimize the best you can with LOD, instanced static meshes, and other areas.

Unless you’re developing for phones and toasters, my honest answer would be “just don’t worry about it”. Suppose in a given firefight you have 20 characters shooting at each other, and each character is holding a primary arm and carrying a sidearm, and each of those is composed of 8 customizable parts. 20 x 2 x 8 = 320 drawcalls. It’s just not that much, especially for something so central to your game’s gameplay. It’s not a bad idea to give some consideration to how your draw calls are optimized but for practical purposes, you’d be better served just going with what works for your modular mechanics, and then worrying about doing better draw call batching on environmental geometry where poor draw call optimization can rack up thousands upon thousands of additional calls per frame.

if you have a mighty need to get your draw calls down, then aforementioned mesh merging would be the way to go, but personally I wouldn’t go that route until you find yourself actually bottlenecked in the render thread.

Wouldnt the automatic instancing make 320 the very worst case scenario?

I was thinking the same thing. I have a 64p w/ 30+ weapons, 10 gear items, nades (5 types). Each pawn will have 2 primaries, melee, pistol, nade, helmet, vest, belt, backpack, clothing items (shirt/jacket, pants, footwear). Each primary weapon will have up to 5 attachments. All of which will be spawned and attached to the pawn.

At any given point, not counting character clothing & skins that’s 22+ (mesh) per pawn not counting materials/MI’s. If clustered together that’s 1,430 draw calls.

Strong possibility of having custom weapon skins as well.

Also, keep in mind that shadows/material slots/skeletons cost draw calls too.

https://forums.unrealengine.com/development-discussion/rendering/1488036-interesting-draw-call-experiment-result

You guys bring up some good points. Thanks for the responses!

Does automatic instancing apply to skeletal meshes? I assumed (and for no reason, it’s purely a baseless assumption) that the batching followed the same sort of rules as ISMs; meshes had to be identical static meshes which could be defined purely in terms of the transform of one relative to another, not just any two primitives sharing the same material. Skeletal meshes having other properties, I didn’t know that they could be draw-call batched together. I guess it depends, too, whether your weapon components are actually comprised of skeletal meshes or just static meshes, but I assumed the former.