How do I optimize for 2600 moving static meshes?

I have 2600 ships that are static meshes that are moving on a spline.

This eats up quite a bit of CPU/GPU power.

I’ve never done any optimizations before.

Any ideas on how to optimize beyond the obvious of reducing the number of ships or making the static meshes simpler?

Have you tried using instance static meshes?

Would that help with 4 different meshes that have all unique movements/pathing? I’ve looked into instanced static meshes before but it seemed like it wouldn’t help from what I’ve read.

You will need one set of ISM’s for each static mesh.
You will have to update the ISM’s instance transforms each frame.

I would try using ISM’s for the visual representation of your ships, But still use a separate Actor for the logic(collision, placement, movement, etc).
You will not be able to use blueprints where you use multiple static meshes to make each ship, Unless you want to use multiple ISM’s for each ship type and then update the transforms.

Is there a reason for separating the actor from the ISM’s? The ships have no collision and I don’t need them to interact with anything so there’s not much to gain from it being an actor.

Then you can just update the ISM from whatever is handling the ships.

Rather then moving the meshes on a spline, I’d suggest that you combine them into a single skeletal mesh and animate them in a 3D Package of your choosing. When you’ve got that high a number of ships, its better to make them a single object. Also this would depend on the poly count of the ships obviously.
Can you give some more detail on what exactly you’re doing in the scene. Is this a cinematic? Are you trying to simulate enemy ships that you’re going to attack? What’s happening?

I can animate it in Maya or something but the point of generating the static meshes along the spline is so I can layout a complicated spline path that matches with the world I’ve created.

Is there a way then to export the static meshes and their paths generated via blueprints to Maya or 3dsMax?

Yeah, select everything in the editor and choose Export Selected. I don’t know if it will export the splines, but it will export the entire scene so you can easily animate correctly.

Again though, I pose the question - What are you doing with the scene. If I have a better idea of why these ships are here, then I can give you a better answer to your problem. My answer will be different depending on what’s happening with the ships after the animation plays etc.

Good to hear there’s an export function.

I’m trying to build a large circuit of traffic. Each circuit is a spline where I generate cars along the spline. They all move along the spline. The circuit is looped and I’m able to move it and shape it all around, creating anchor points where need be. The cars go through some very tight spaces on the map so their path has to be closely controlled.

I construct the static meshes and then use the event graph to move them.

Given this, would it still be best to animate in Maya? Will the movement carry over or will I have to animate each and every single car? If I animate every car, it might be difficult to get the cars to follow the exact pathing (and it needs to as there are some tight spaces).

Please advise.

Oh! You should check out the Shooter Game demo. You can download it from the Learn tab. They’ve actually got something similar set up using a particle system. You could easily migrate the particle system to your project and just swap out the mesh that’s used. No idea how they set the path the particles follow but with a bit of research I’m sure you could figure it out.
The benefit of using a particle system is that the ships would fade out after a certain time so there’s less hit to the draw call and you could likely use the same mesh without noticing. You’d definitely want to get your ships down to a low poly count though… probably 1,000 tris max.
My guess is if Epic chose to use a particle system for this effect, then its the best way to approach it.

I’ve looked at their demo and have tried it beforehand. Their method doesn’t work for us because it’s very hard to set exact pathing. Setting pathing via velocities/lifetimes is very unintuitive and only works well for very simple circuits.

Could you kindly answer my questions from above?

I appreciate the help so far.

Do you actually have to have 2,600 unique paths? I’d imagine that you only need to have a few paths, maybe 10 or so and then you could just model out a “cluster” of ships to make it look more crowded and animate them along the path. If you’ve already got the paths set up in UE4 then you might as well stick with doing it inside the engine. What I’d suggest to optimize your scene then is to group as many of the vehicles into a single mesh as possible. I’d say 100 vehicles in a single FBX file and stagger them out however you need. Also at this point you’d want your ships to be closer to 500 tris (or less) each so that a single cluster isn’t higher than 50,000 tris. Then you only need to place 26 of these clusters into the scene which would reduce your draw calls dramatically. Remember that in space (or air) you can use the Z axis (height) to make things seem really crowded without taking up as much space along X and Y. Also if you only model out one or two clusters, then instancing will also help reduce your draw calls and maximize FPS.

I have 2600 cars, but about 10 splines/circuits/unique paths. Each spline has multiple cars on it, somewhere around the range of 50 - 200 cars.

I can’t batch multiple meshes together into one because there are curves in the spline and the ships have to individually rotate with the spline or else it’ll look like a glob of cars turning together.

Will instancing still help if I’m not combining cars into clusters (as in combining multiple cars into a single mesh)?

Nope. 2,600 cars would be about 2,600 draw calls. Possibly more since the engine wasn’t built for that scale of instancing. You don’t have to model the cars as a blob. Lay them out in a line.
I’d probably suggest that you do it inside Maya then… lay them out in a line and you can use something like a path deform to have them follow the shape of the spline.

So, let me get your recommendation straight: Export the spline I’ve created. Use that as a guide to animate the cars’ paths in Maya. Is that right?

What are you talking about?
Instancing is a hardware/driver feature where you tell the GPU to draw the buffers N times with N amount of data.

Yeah but you can’t instance thousands of objects without taking a performance hit. Here’s a comparison I put together for another person with a similar question. The scene consists of 4,200 cubes. The first screenshot shows all cubes contained in a single FBX file and the second is a single cube duplicated 4,200 times in engine :

Instancing definitely saves on overhead but its not a 1:1 ratio otherwise games would literally be able to have unlimited poly count.

And Cloudent - I don’t use Maya personally, I use 3Ds Max but I’d imagine that Maya would have a similar functionality that is the ability to deform a mesh along a spline. So what I would do is line up your ships in a row (some can be side by side, some on top etc.) and then use path deformation to have the ships adhere to the spline then bake the entire scene down before exporting to UE4 if you need the ships to follow the spline precisely.

My ACTUAL recommendation would be to revise your current design in several ways so that you can better take advantage of the engine’s capabilities. I’d re-design the area so that the ships don’t have to adhere to the spline so tightly and use particles to render out the scene. I’d also think about how important this scene is in the grand scheme of the entire game. Ultimately you’re going to have to figure out a way to work with the engine’s limitations.

And how do you know that the editor automatically used instancing for those 4.2K cubes?

And yes, A single large object is for the most part better then lots of (small) individual ones.
Instancing issues ONE draw call, Which is where a lot of the overhead happens (It still needs a secondary buffer for the per instance info).

D3D12 and Vulkan mostly make this a moot point.

I was under the impression that duplicating a mesh was the same as instancing one. Obviously this is not the case?