Two part question…
Part 1:
I am spawning ~500 actors, then as the game is played the player’s actions can cause these actors to get destroyed. The actors are static mesh actors (AStaticMeshActor). It works fine except the performance is horrible.
For these ~500 actors, I don’t care about lighting or physics or ticks or anything. They are just simple one-color boxes that I want to be visible to the player.
How do I get the maximum performance out of these actors? If I was writing the same program with C++ and OpenGL (or DirectX), this would be easy to accomplish. So I know it’s not an issue of my host hardware which is very fast. The problem is that UE4 is slow for no good reason. There must be a way to turn off whatever useless activities UE4 is doing with each of these 26x19 actors? How can I disable lighting, physics, ticks, etc?
I want to disable any and all things that affect performance. The ~500 entities don’t even have to be “actors” if there’s a faster alternative. All I want them to do is to be physical boxes that the player can see (and again - they don’t even need lighting).
Another idea is to use instancing but I don’t think that should be necessary because from an OpenGL perspective the way I’d implement this is a single list of vertices, primitive type is triangle list, VS just does model world view transform, then pass-through PS just outputs a hardcoded color (eg gray).
Part 2:
If I was writing this in OpenGL/DirectX, I’d draw all ~500 entities in a single draw call because they are all the same material. The ~500 entities are just one-color boxes (eg gray boxes) and they are all the same color. So in OpenGL/DirectX, it would just draw a triangle list from a list of vertices. The list of vertices I could update as needed. I know how to do it in OpenGL, but how do I it efficiently in UE4? Does the materials system handle optimizations like that? Ie if I have multiple actors with the same material, will UE4 combine them into a single vertex buffer and draw them all in a single draw call?
Update:
Re McStrife: The cubes are generated with C++ code:
AHQGrayOutActor* pActorGrayOut = GetWorld()->SpawnActor(AHQGrayOutActor::StaticClass());
AHQGrayOutActor extends AStaticMeshActor because that makes it easy to customize my cube. However, it doesn’t need to be a static mesh if there’s something else I can use instead?
The cubes do not require any shadows or lighting or physics or collisions or ticks or anything except to be drawn. This is why I explained how I would do it if I wrote my app from scratch using OpenGL.
Re HungryDoodles: SetMobility(EComponentMobility::Static); in my AHQGrayOutActor ctor causes me to get a warning message “LIGHTING NEEDS TO BE REBUILT”. I’m guessing this is because my actors are generated in C++ code? The reason I do them is C++ code is just because there’s 26x19 of them in a grid so it’s easy to position them in C++ code. I’m not sure how to do that in the Unreal Editor.
Update 2:
I’ve attached a screen shot. Basically all I’m trying to do is “gray out” (using black boxes) unvisited portions of a board - in other words “fog of war”. I’m open to doing it a different way. Eg dynamically edit the board texture. Eg generate scaled static mesh actors of varying size - ie instead of 26x19 1x1 squares, my C++ code could search for the largest possible black rectangles starting with a single 26x19 box.
However, consider the following. In OpenGL, we could draw a box with 12 triangles. 26x19 x 12 = 5928. By not drawing the bottom side of the cube, we could reduce it to 26x19 x 10 = 4940. The VS/PS for my desired output is basically the simplest possible shader - VS just multiples pos by ModelViewProj, PS just outputs a hardcoded color. Any modern GPU, even $100 previous generation cheap Android smart phones can draw millions of triangles a frame. Doing a single draw call for ~5000 triangles with a pass-through shader shouldn’t be expensive. I’m assuming it’s only expensive because UE4 is doing stuff I don’t want it to do. So there must be a way to tell UE4 to just draw the triangles with a VS/PS and to not do anything extra - no physics, no ticks, no shadows, no lighting, no nothing etc.
Thank you for any leads on this.
Update 3:
Another idea is to have the entire fog of war be a single actor with a static mesh that is dynamically generated. I wonder - is there a way to dynamically generate vertex positions for an actor’s static mesh in C++ code?
Update 4:
I suppose what I want is called “draw call bacthing” . The idea is to have objects drawn with a particular material to be combined into a single draw call by combining their vertex buffers into a single vertex buffer. Because of culling (we can gain performance via CPU culling of objects based on a bounding box) (and objects can be far apart), it might make sense to have the developer specify which objects to batch (either that or have UE4 group them intelligently eg based on distance). From what I’ve read, UE4’s instancing doesn’t actually reduce draw calls - it just groups them (ie do all the draw calls for a same material in a row).
I was naively assuming this happened automatically… But apparently UE4 does not support this (but Unity does)?
Update 5:
I’ve attached a second screenshot of the board from a different angle.
As far as the details of the graying out… The color (gray, yellow, red, dark gray, black, etc) is TBD. Whether it’s transparent is TBD. Whether gray-out modifies the board texture vs. adds a small height is TBD (in the screen shots, the actors add some height).
In this third screen shot you can see what I mean by height: