Which one of these is more taxing: Keep in mind, this is on void Update, and 99.9% of the time those bools are not changing(Meaning its spamming something that has already been applied). Thanks in advance
I dont exactly know how optimized SetBool is at runtime, but:
One statement evaluation is basically neglectable performance wise
Either way both options are O(1) runtime, so neither should matter.
As a rule of thumb, dont start optimizing unless you are experiencing performance problems. If anything, worry about the efficiency of things that scale over the number of elements in a list, for example. If you are concerned about performance, you can take a look at the profiler. To figure out exactly how long these calls take, measure the time before and afterwards and print the difference. The resulting time should be in the nano to micro seconds order of magnitude. So doing it every frame (which is every 4-16+ milliseconds) is of absolute no concern.
While it shouldnt really matter either way for this example, assuming the executed code part to be a bit more expensive, then option A would definitely performe better, since you are executing it less often. However, if the execution is very expensive, it may still cause a noticable hickup in the framerate. So while your overall framerate would be higher, the actual experience wouldnt be better. So for most very expensive tasks it’s best to not run them on the main thread at all, if possible. But again, none of this should matter for this example.
I personally like option b as it would only be called when the event is true. It would evaluate every update tick but that is trivial. Your issue may be that performance is obfuscated as it will only degrade (if at all) when the event passes true. I think in this case it will be negligible. Best way to be sure is to run some of your own tests and profile each.
I do Have a performance issue, and this script seems to be the main reason for it, so I am trying to optimise everything in it. the script it about 1000 lines and this script is placed on every single unit in an rts game. so every little bit counts. Been trying to optimise this script for 2 weeks now, because I need to expand it soon and that will only make it harder for me to Zero in on the problem.
the Code is incomplete, it has a lot of empty functions etc waiting to get filled… and its quite large and very very messy lol, I am afraid to post it lol
I’m assuming you plan on having hundreds / thousands of units? If so, then having one or multiple Monobehaviors per unit is going to become pretty slow no matter what you do there. Ideally, if you want this many units, you’d use something like the new DOTS which can easily handle tens of, or upwards of a hundred thousand units on any modern computer. You could use a hybrid approach and only handle animations and rendering through it, but then again, having Monobehaviors on every single unit gets slow eventually. You can lighten the problem a bit by having a manager class, like an AnimationManager, which is one Monobehavior and updates the animations of all units, instead of every unit doing it for themselves. Then do the same for all things units do. Having it all in one class should also make it comparably easy to get it off the main thread, using Jobs + Burst.
I guess it would be a bit of an effort, and not exactly easy for a programming beginner like you said you are.
So for now, how many units will there be in your game roughly? How many result in the screenshot performance you showed above? How many Monobehavior scripts are on each unit? What are these scripts doing? And on what hardware are you testing?
I agree with you, but as you said, multi-threading etc is beyond my skill-set, also I am waiting for unity to make it more optimised and user friendly before I get into it. but that surely does seem the way to go to make the game with my original design of having 1k+ units. Thus I have decided to make the game smaller, that profiler showed 200 units total.
I have had this suggestion many times, but I have no idea how to do it, I was able to do this for the Health bars so that they face the camera at all times, but I am not sure how to implement this for Animations. I mean, my animations are linked to my Movement/attacking and targeting. and every unit can be in its own state. theres so many if/else statements also.
It has also been suggested to me, “instead of having an update function on all units, use a unit manager”, and i dont know how a unit manager is going to iterate though a list of 200 units that have very big scripts. some of which have many functions such as “if unit selected && you click this and that”.
This one is my most taxing script and I am only 1/2 done with it. I am just making sure what I have made is functional/optimised before I continue working on it;
------------------- Only read for curiosity ---------------------
If you started programming in Unity, then you are used to scripts being Monobehaviors. However, technically Monobehaviors are just one specialization of normal objects from OOP. Monobehaviors are objects that give you the option to implement certain methods (like Start, Update, ..) and are handled by the Unity engine, which includes iterating over them and calling the methods at the right moment. However, due to the flexibility of the system, there is some overhead involved. The idea is to get mostly rid of this overhead. For that, you can remove the “Monobehavior” part of the class. This means, however, that Update() wont automatically be called anymore. You now create a class, like a UnitUpdater for example, which has a list of references to all of your units, and is a Monobehavior itself. In its Update() you simply call the unit.Update() of every unit that exists. You obviously need to make sure that you keep the list of unit references up to date, when you kill or spawn some, but that’s about it.
Now instead of each unit.Update() handling a lot of things, you could also split it up into smaller methods, like Move(), Attack(), … and so on. You can now do some optimizations, where you only need to call these methods, if they are actually applicable. Just as one example, you could calculate which units are actually in range for combat actvities (using something efficient like an OcTree, but we are getting a bit ahead of ourselves now), and then only call Attack() on the subset of units, which actually have to check if they can or should attack, thus reducing the overall code that needs to be executed.
However, you are using pretty high end hardware and if we are only talking about 200 units, then there is no way Monobehaviors are the main problem here. The frame times should, afaik, be nowhere close to 30ms. I mainly explained the above for the sake of explaining it, but i doubt it will do a lot for your problem.
I’m honestly not sure what best to do in your case,
but when looking through your profiler screenshots again i noticed a couple of things:
You are creating quite a bit of garbage per frame. This is bad, since the garbage collector will eventually need to collect (clean up) all of that, which is rather expensive and will probably cause spikes in performance once every couple seconds. So you should prevent creating object references in Update. If you use helper classes that are only temporarily used, dont. Instead, use value types like structs. As for gameobjects, try something called object pooling. Doing these two things should mostly get rid of your garbage creation.
Your Coroutine for attacking infantry seems to be taking up a lot of time. How often is it running? What exactly is it doing? Do you actually need a Coroutine? While introducing concurrency, Coroutines are mostly there for conveniences, not to introduce any kind of multithreading (it does not) or true parallelism, so if you have tons of units interrupt the main thread to execute their Coroutine content, then this is probably a bit problematic. I personally dont use Coroutines so i cant say a lot more about that.
Looking at the graph, everything looks like it is taking a lot longer than it should, even rendering. What else is in your scene? Because 200 units should most certainly not have 1.5m triangles. So if you actually use models with 1500000/200 = 7500 triangles per unit, then.. dont. You do not, ever, need this level of detail for an RTS. I’d say you can decrease the triangle count to something between 100 and 1000, depending on the detail and zoom level you intend. This should highly cut down on your rendering times. I’d say 1700 batches for 200 units it also quite a lot, so you may wanna look into that. Having 1700 batches basically means your CPU needs to tell your GPU 1700 times per frame to draw something. And communication between CPU and GPU should be kept to a minimum.
Hope this helps a bit. While i have a pretty decent understanding of performance, i’m not exactly a Unity veteran either, so hopefully somebody who has been longer around than I did can tell your some more.
Edit: In your scripts, are you by any chance going through every possible target on every unit to decide to, for example, attack? Because that’s going to get slow very fast with increasing amounts of units.
Also, are you by any chance using anything along the lines of Find() or FindGameObjectWithTag() to get references? Because those should only ever be used for prototyping. They are very slow.
Thank you so much for taking your time and replying, I think I will make a video and explain what I am doing in detail.
No I target units dynamically based on onCollisionEnter with a 40 radius. same with deselection.
I dont use “Find” at all, at max I use get component and most of those I cache if possible.
Its 2:20 am right now, and my 2 year old is awake! lol, I will make a video and post it here tomorrow with much more details. I will go through exactly everything I do.