- Home /
Does it help performance to first check if some transform attribute has changed before setting it?
If inside an Update you set an object's position, but the position might not always be changing, does it make any difference at all whether or not you redundantly set the position to the value it already is?
i.e. Does this save you anything?
void Update()
{
Vector3 nextPosition = new Vector3(x, y, z);
if (transform.position != nextPosition)
{
transform.position = nextPosition;
}
}
Compared to this:
void Update()
{
Vector3 nextPosition = new Vector3(x, y, z);
transform.position = nextPosition;
}
Cool, thanks Llama_w_2Ls! What about if the object is a UI element on a Canvas? Do you know if you have to re-render the whole Canvas even if the new position is the same as the existing position? (And then maybe it'd be worth to check first)
Is there a reason you are instantiating a new vector to tests its values? wouldnt this be more performant/ optimal (if marginally)?
if (transform.position. x != x && transform.position.y != y && transform.position.z != z)
{
transform.position = new Vector3(x, y, z);
}
Answer by Hellium · Jan 10, 2021 at 05:35 PM
Setting the position every frame has really almost no effect of performance, for a computer of our age
Try to move hundreds of entities every frame and I can guarantee you will see a drop of your FPS.
There is no absolute yes or no to this question.
IT DEPENDS.
If the object you move has a complex hierarchy, moving it to a different position can affect performances. If it has many parents, the local position must be computed according to the hierarchy to match the desired world position.
Changing a canvas element dirties the whole canvas (position, color, animation, ..., ANYTHING)
I did a check with the following code:
float x;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
x += 0.1f;
}
transform.position = new Vector3(x, 0, 0);
if(transform.hasChanged)
{
Debug.Log("Has changed");
transform.hasChanged = false;
}
}
The flag hasChanged
does not turn to true
unless I'm pressing space, so I guess Unity does some optimisation to avoid unnecessary computation if the new position is the same as the old one. Meaning your check may not be needed.
I highly advise you to profile your game instead of trying to optimise things without knowing if it will have any effect.
Yep. $$anonymous$$aybe another thing to add is just going and reading one of the many things on the internet explaining why "premature optimisation is the root of all evil".
I want to chime in quickly to point out that this might not be as reliable as you're hoping. To quote the documentation on Transform.hasChanged...
Note that operations which can change the transform will not actually check if the old and new value are different before setting this flag. So setting, for instance, transform.position will always set hasChanged on the transform, regardless of there being any actual change.
I'll also take this opportunity to point out that that (incomplete) phrase regarding "premature optimization" has been interpreted and extrapolated far beyond its original scope.
Consider two different ways of presenting this integer multiplication of 5 times 2:
int a = 5 * 2; // 10
int b = 5 << 1; // Also 10
// For reference, if your compiled code ISN'T using the bit shift
// for power-of-two multiplications, then there are bigger problems here
Which looks more like the original equation and which looks like it would be (logically) drastically quicker to calculate?
Just because there are sensible optimizations that can be made doesn't mean that they shouldn't be made, and it's sensible to know what should or shouldn't be considered ahead of time. For example:
if(gameObject1.CompareTag("gameObject2.tag"))
// ... is faster than
if(gameObject1.tag == gameObject2.tag)
Bringing this back around to the original question, it does return to the logical answer that, well...
IT DEPENDS.
Whether the position needs to be updated every frame or not, as well as how varied the new positions need to be means there are a lot of potential variations on how performance may be affected. A single controller setting the positions of 100 Transforms every frame is far more efficient than 100 scripts attached to 100 GameObjects setting their own positions, due to the (unseen to us) overhead of having the scripts and processing each one's Update() functions. However, you then also have to carefully verify that you're properly monitoring each GameObject correctly, to avoid missing when they should be added or removed from the List(s) that are iterating through them.
I want to chime in quickly to point out that this might not be as reliable as you're hoping. To quote the documentation on Transform.hasChanged...
Note that operations which can change the transform will not actually check if the old and new value are different before setting this flag. So setting, for instance, transform.position will always set hasChanged on the transform, regardless of there being any actual change.
I did a try on Unity 2019.3 & Unity 2021.1b and the Has changed
was printing in the console only when I pressed space. I did not find a way to get a message printed when the canvas was rebuilt (did not manage to make ICanvasElement work). Anyway, I've explicitely used modal verbs to indicate the check may not be necessary. Profiling the two solutions will give a proper answer.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
Context doesn't really change the point here :) The point was for anyone co$$anonymous$$g to this obsessing about optimisation to go away and investigate and think about it.
Thanks yall! For those worried about premature optimization, it's a valid point, but rest easy knowing that's not what's happening. Purely just curious because I've seen other people code updates both ways, with the check and without, and it made me curious if there was any difference or if Unity's calculations made it redundant.