Hello I am making a Space RTS called Interstellar: The Endless War.
I need help optimizing performance to squeeze every bit of juice out of Unity that is possible. I’ve made huge strides in the last few months improving performance, however I still have a ways to go. Any Ideas/Feedback are welcome. Your help is appreciated.
My goal is to have 200 ships, ~600 weapons, and 5000 ammo in flight at any given moment (with a FPS > 15).
Here’s a video with the profiler running and some info below for context.
Looking at performance profiling. There are:
~106 ships on screen (most are fighters so difficult to see
~300-400 weapons firing independently
~500 to 2000 ammo shots in flight
Each object including ammo has its own collider and is being driven by physics.
Models are to scale, which means the ammo is flying to scale which means it s moving at just north of 300 m/s.
Here is my WIP thread and my YoutTube channel. Please leave comments there or here.
I have impression that every projectile is a separate object. And is being rendered as a separate object. Judging by the graph, the majority of overhead is from rendering routines. The second major overhead is from physics.
If projectiles can collide with each other, you should try disabling that.
If they’re rendered as separate objects, you should think about making a global system to render all projectiles at once.
Then, there’s a possibility that your ships are using non-convex mesh colliders for everything, which could be bad.
Also, with high speed, you may run into floating point errors quickly, but that’s another story. Unity is a singe precision engine.
I do not think Garbage is something you’ll need to worry about, if you’re developing for PC platform. Besides, garbage generating information in editor is useless (because editor allocates helper structures) If you want real data, you should build a project a connect to it via profiler.
RE: Interstellar. Not the point of this thread, but since you brought it up. The full name of the game is Interstellar: The Endless War.
RE: Instantiation. I developed some advanced pooling that I am using. Not one single object is instantiated in the vid I posted. If I was instantiating ANYTHING on the scale of the video, the fps would be < 0 lol
Yes EVERYTHING is separate objects, also, there are MANY object beyond the ships/ammo/weapons that are part of the scene and not being rendered in the vid.
I did turn off Ammo to Ammo collisions, and that did help quite a bit. (It was the first thing I did to optimze). My collision layer matrix is optimized across the entire scene (ie, only things that should collide are allowed to collide). However I was wondering if there is a possibility to optimize that even further. If I could limit collision detection to local regions, that might be something however I wouldn’t know where to start with that.
Colliders shapes are mostly optimized (no non-convex meshes and mostly using primitives where possible.
Remarkably, float point is not an issue. Unity has come along way in last 4 years.
Garbage collection WAS an issue, I have eliminated the biggest culprits and will continue to eliminate temp variables where I can, but as of right now, Garbage collection is low priority problem at the moment.
5.a) What do you mean by: “If you want real data, you should build a project a connect to it via profiler”.
@salex100m : whether it has extra words in the name or not doesn’t matter. No mans sky about had to change their name because it had the word “Sky” in it, because that word is Trademarked.
They even beat Microsoft because they had a product called, "Skydrive " and changed to “Onedrive”, and also Skype is not Trademarked by Microsoft because it’s logo is to similar to the Sky trademark owners logo.
I’m just trying to tell you to be-careful, because that’s very very close to the name of the movie, and Hollywood people are quick to sue over anything to make their 25 million.
@Martin_H : A few things/notes. Also thanks for the indepth thoughts. You make some good points
first off: I didn’t include the stats window on purpose, the FPS gets lagged due to 1) the profiler 2) the scene view 3) other things running on my CPU. Also I am object pooling (my own somewhat advanced design). So assume that is optimal for now.
RE: Rendering:
a) As the vid shows, my biggest lag is the renderer. I have many similar meshes and materials that are being rendered. I believe this is my next avenue for optimization. However I don’t know the first thing about this yet. I am using one large texture across all the ships. The ammo and fighters are NOT optimized yet. Also I have not optimize other things (not shown) like the GUI elements, reticles, etc. I believe I can get big gains here, however I don’t know how yet
b) How do you “manually merge geometry with a script?” Do you mean (for example) take two primitive unity cubes and make one shape out of them, thereby reducing vertices? How do you go about that? Any examples?
c) Also curious about the “instancing shaders” you mentioned.
RE: Physics/Triggers. I have optimized my use of colliders. For the record, pushing as much STUFF to the physics engine is actually a good idea. I saw some tangible gains by offloading some movement/transform code to the physics objects. I havent tried raycasting on the projectiles, for various reasons. Mainly because I want the projectiles to be as dumb as possible. If I have 5000 projectiles on screen all of them updating their raycasting… that would be bad. What I really need is a collider that is a line :). Does such a thing exist? It should!
Not sure about batch rendering, for projectiles or otherwise.
Here’s a hypothetical question: If I make one super texture (say 4kx4k) , and apply it to all my models. If I have 10 models using that texture/material, does that 4kx4k get multiplied by 10 anywhere? In the rendering? In the memory? (I don’t care about memory)
RE: Profiling, about profiling in editor/versus build: Yes there is significant difference between editor and build. However 1) I don’t know how to profile in the build and 2) Why does it matter? If I can improve the editor version, than that should improve the final build right? At least is has so far in my optimization journey.
That being said, can you recommend a tutorial or something to show me how to profile in a build? Worth doing at some point if it takes some time.
Actually, I’m fairly sure PHysX already is supposed to optimize collision in regions under the hood (via one or other broad phase optimization algorithms)
“Build and run” with profiler attached instead of Running it in editor. You’ll have different data.
Can’t give any extra advice - beyond what you already told, I’d need to work on your project to see if anything can be improved.
You’ll have only one instance of texture in the memory, however materials with different parameters that use this texture will generate additional draw calls.
Wrong. You may end up wasting time fighting issues that do not appear in release mode. For example, running things in editor generates extra garbage that does not even happen in actual build.
That’s not how trademarks work. There’s no indication that anyone filed a trademark for the movie title (it’s not automatic like copyright, and titles can’t be copyrighted in any case), and while there’s a trademark filed for “interstellar”, it seems to be for beer, for some reason. Trademarks in one industry don’t apply to others, though that doesn’t necessarily prevent the owner from bringing legal action if they think there’s reasonable grounds for confusion. Also note that No Man’s Sky didn’t change their name in the end.
“Actually, I’m fairly sure PhysX already is supposed to optimize collision in regions under the hood (via one or other broad phase optimization algorithms)”
Do you have a reference source you can point me to? I’d love to know if this is accurate. Do you know if there are any exposed parameters or adjusting that I can make to opitimze it even further through Unity.
RE: RayCasting. if I raycast and update every frame (or fixed frame) I’m 98% sure that would be slower than putting a sphere collider and moving via rigidbody. Is there a PhysX way to raycast that would improve on the collider?
@Eric5h5@N1warhead_1 PLEASE FOR THE LOVE OF GOD STOP TALKING ABOUT THIS ON MY THREAD.
Thank you kindly
This thread is about OPTIMIZATION OF CPU/GPU/PhysX performance Only. Thanks!
Feel free to discuss other: gameplay/issues/aesthetics/names/ or other various legal nuances on my WIP page. Let’s keep this thread clean and hopefully other folks might learn something about optimization.
@neginfinity
Thanks for that resource slide presentation. Has plenty to think about!
@Martin_H@neginfinity
You both mention profiling IN build. Do either of you have a resource on how to do that? Maybe there is an asset on in the store? Or does Unity Pro do this? Does Unity “noob version” allow this?
Good point, but its not an option for me. However someone recently mentioned the idea of using LODs to optimze far away objects. I was thinking about going that route and also using textures as LODs.
Without broadphase optimization, you’d most likely have single digit fps with the amount of objects you have.
I wouldn’t think this way without measuring first, and would expect opposite, because raycast does not participate in simulation itself. The only issue is that some of raycasting functions return arrays, meaning more allocations, but there’s RaycastNonAlloc available. Not sure if replacing colliders with raycast will help, but giving it a try might work. Oh, and keep in mind that if you try to use SPHERE cast, then it’ll fail to detect collision when the other object is already within the bounds of sphere at the beginning of the sphere ray.
Also, continuous collision detection mode is supposed to do something similar to raycasting, in order to prevent objects tunnelling through each other.
Another issue is minor overhead from having update/start methods in monobehaviors, but that does not seem to be the issue in your performance graph.
Also, keep in mind that in addition to raycast I mentioned capsule collider.
Your main problem is mesh and texture.
I asked you to change all small fighter by cube just to be sure this is your problem, after it’s sure you will have to use LOD system.
What type of shader do you use?
I have more than 200 Mechwarriors in my game and I can reach 400fps.