- Home /
Which Unity functions are generally slow/bad for performance?
As a fairly novice Unity developer I have often found it difficult to find out which Unity functions are particularly heavy operations and should be avoided. Even the Unity documentation doesn't mention whether a particular function is performance heavy or not. Not knowing beforehand obviously makes the learning process a lot slower because you learn how to code something one way, and then later find that in terms of performance it is an absolute no, and have to start all over again.
I think it would be useful to make a list or groups of lists of Unity functions starting with generally those most performance heavy. Obviously some functions depend on how they are used, so this won't be a "no exceptions" list, just a general guide for novices like me.
You can edit your question and check the 'Can others in the community edit this?' found to the bottom right of the text edit box, if you want to make it easier for everyone to update that list.
The problem is what you mean by "Normal" - because there's no way that list is in any kind of correct order right now and it's hard to correct it because it depends on where you consider calling them...
Like whydoidoit said, a one-time call to Broadcast$$anonymous$$essage isn't bad for performance, but putting it in the Update loop might be bad.
Similarly, I think the sneaky culprits are $$anonymous$$onoBehaviour properties like transform. Beneath the hood, the transform property actually calls GetComponent. If your Update loop has something like this:
void Update() {
transform.LookAt(myTarget);
}
You're actually calling GetComponent every update!
Thanks for the input guys, I hadn't checked back here for a few days but I like where this is going. This has been needed for a while! As I said, feel free to change the list around into an order that makes sense and add more details as you see fit ;)
Be nice if you linked each function in the list to its documentation. (Yeah, I know I could do it myself now that it's a wiki question ... ;) (EDIT: I see someone's done this now, nice, thanks!)
Answer by Hamesh81 · May 15, 2013 at 03:31 AM
Please feel free to add/remove/make suggestions as I am only guessing here:
Super Heavy
Resources.FindObjectsOfTypeAll because it loads all of those resources (and is clearly super slow at searching anyway)
Heavy
GetComponentsInChildren (etc)
BroadcastMessage, SendMessageUpwards depending on the number of children/parents
Medium
SendMessage - it's fine for events don't use it every Update/OnGUI etc
OnGUI (but it's more about the number of things you put in it)
Low (but worth considering)
transform.position, transform.rotation for things with parents
Debug.Log is slow if called every frame
I can attest to Debug.log, I actually found it to cause surprising slowdown, when I was using it to print items in a List.
@Steviebops: Debug.Log or print is only slow inside the Editor. In a built game it's not that bad. Some things in the list above are not really correct or at least can't be compared to others.
How come GameObject.FindWithTag is considered "$$anonymous$$edium" slow? Shouldn't it be like a pointer or list of pointers that is quickly accessed? Especially if you have only one GameObject tagged "Player" ?
I also noticed the Start() event on monobehaviours -- even if that Start() routine is fully empty -- is getting super-lagging if you have a lot of gameObjects (Unity 2017.2 final). When I removed the Start() event to init something and ins$$anonymous$$d did a check in update every frame that would then init once, area load went down from 27 seconds to 7.
I'll add that there's one major thing about Unity that makes an huge difference when accessing functions and that's which kind of data you feed it. Developers who works on Unity has explained many times that Unity generate new blocks for every "new data" and doesn't clean unused blocks until the app/built is closed down.
This means that you should, ideally, always use existing values ins$$anonymous$$d of creating new ones on the fly.
//This is bad as it create an unique block each time you call FindWithTag.
Destroy(GameObject.FindWithTag("ToBeDestroyed_A");
Destroy(GameObject.FindWithTag("ToBeDestroyed_B");
Destroy(GameObject.FindWithTag("ToBeDestroyed_C");
//This is better since it only create an unique block for Target once and reuse the same block afterward when necessary.
GameObject Target = GameObject.FindWithTag("ToBeDestroyed_A";
Destroy(Target);
Target = GameObject.FindWithTag("ToBeDestroyed_B";
Destroy(Target);
Target = GameObject.FindWithTag("ToBeDestroyed_C";
Destroy(Target);
It's highly suggested when working with strings multiple time to create Hash of those strings and calling those Hash ins$$anonymous$$d as it keep reusing the same block ins$$anonymous$$d of creating a new one each time.
What you wrote there makes no sense at all. What unique block do you talk about? Intermediate results of chained method calls are either placed in CPU registers or in local variables on the stack. Also your second example is actually the bad one from a code design point of view. Storing intermediate value in a variable that is only used once just makes the code more complex. The allocation on the heap isn't changed whatsoever
Have a look at the compiled IL code of your two examples.
Stack memory is immediately cleaned up as soon as the method returns. That's the nature of the stack. Heap memory on the managed side is completely controlled by the garbage collector. Once all references to a memory block are gone the memory is up for garbage collection. Besides that there is native heap memory in the engine code. It's completely managed by Unity. Things which are allocated has to be cleaned up by Unity or a method Untiy provides. There are objects (like all UnityEngine.Object derived types) which are tracked objects on the native side. Those objects need to be destroyed manually by using Destroy when you don't need them anymore. However it doesn't matter how many variables you use or how many variables are referencing the same object.
Furthermore string constants are actually interned strings. You only create new strings when you combine them at runtime. For example
This:
Destroy(GameObject.FindWithTag("ToBeDestroyed_A");
Destroy(GameObject.FindWithTag("ToBeDestroyed_B");
Destroy(GameObject.FindWithTag("ToBeDestroyed_C");
Is much better than this:
string name = "ToBeDestroyed_";
Destroy(GameObject.FindWithTag(name + "A");
Destroy(GameObject.FindWithTag(name + "B");
Destroy(GameObject.FindWithTag(name + "C");
While the first example uses 3 interned constant strings which are loaded with the assembly, the second example creates 3 new strings each time which need to be garbage collected.
Answer by toddisarockstar · Dec 01, 2015 at 04:11 AM
in order of worst to least. Overlapshpere, raycastall, raycast, and vector3 distance. are all mistakes i made to forse the rewrite of my last project not on your list. they are wonderfull tools but must be limited depending on your project.
something as simple as :
var frame:int;
frame=frame-1;
if (frame ==0){frame=10;
//---now check a heavy sherecast your game needs
}
can lighten the load on your cpu greatly it all depends on what you are doing. one thing i found is that the friendly game engine developers with unity created colliers that DO NOT slow game progress. i have tested thousands in a level.
any type of "Find" or "lookup" should never be called more than once! anything more should be stored in a variable or array for fast lookup.
"destroy" should be avoided. things like bullets are recycled...not destroyed.this also reduces the need for instaniate. even though unity does it automatically, there is a term called garbage collection. where a system goes through a laggy proccess of freeing ram memory for things "destroyed". its better to move bullets under terrain untill recycling or make them invisible when not in use.
debug and print definally slow a game.....when code blocks are desireable delete for final builds.
i havent seen evedence of asking"position" or rotation slowing things but if you where worried you could also pack a common request in the top of your update. i do that just for easier typing somtimes in a longer code.
var tp:Vector3;
function Update(){
tp=transform.position;
if (tp==this){do this;}
if (tp==that){do that;}
}
everyone complains about the gui system being slow. if you want to pick up on a mouse click on a position. why not put it in your update???????
function Update(){
sw=Screen.width;
sh=Screen.height;
mx=Input.mousePosition.x;
my=sh-Input.mousePosition.y;
if(Input.GetMouseButtonDown(0)){
if(mx>sw*.2){if(mx<sw*.3){
if(my>sw*.2){if(my<sw*.3){
//i know you clicked a spot on the screen without a giu button
}}}}}
remember that all unitys funtions are basically something in your script that you dont see. depending on the function, unity could run hundreds of lines of code, potentially on hundreds of different objects in a scene on the frame you call some of these options. then your game waits for a return from unitys scripts/functions.
for large games accomplishing big things professional developers use several technics that are specialized for the problem in your game. such as as only checking a distance for things within a specific camera distance or packing references into super fast arrays or lists for lookup. if you could give us details about your game and what you think might be slowing it, we can give you some ideas on how to get around it!!!
Answer by anilo · Dec 01, 2015 at 01:15 AM
GetComponent or FindComponent is heavy but there is no harm if you complete these steps at the beginning of the level.
Just don't put them in your Update method.
What I typically do is populate the components in a local array at the beginning of the level by making all the needed getcomponent calls ahead of time.
This allows me to access these components from my local array during the gameplay, which is of course much faster. But, it takes work.
Answer by kostas-vs · Sep 01, 2021 at 03:16 PM
Not as heavy, but worth knowing that magnitude and normalized of vectors can be somewhat slow since they involve square root computation.
As mentioned in the first link:
If you only need to compare magnitudes of some vectors, you can compare squared magnitudes of them using sqrMagnitude (computing squared magnitudes is faster).
Your answer
Follow this Question
Related Questions
c# Adjust In-Game audio 1 Answer
How can I have one script wait for a whole bunch of scripts to finish running a function? 0 Answers
How Can I Reduce Build Time for Script-Heavy Projects? 2 Answers
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Scripts optimisation 2 Answers