Vector3 name = new Vector3() vs. Vector3 name.set() ... which is faster?

Hi there,

I’m relatively new to coding (particularly in c#), but recently saw two different ways of setting parameters in a Vector3, as follows:

Here’s what I wrote initially;

public class Player : MonoBehaviour
{
    void FixedUpdate()
    {
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        Vector3 movement = new Vector3(h, 0f, v);
        Move(h,v);
    }
}

Simple enough and works just fine. However, I then saw someone else write the same behavior with the following;

public class Player : MonoBehaviour
{
    Vector3 movement;
    void FixedUpdate()
    {
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        movement.Set(h, 0f, v);
        Move(h,v);
    }
}

So, without having any insight as to what’s happening behind the function/method, it appears (on the surface) that the first version is re-creating a Vector3 from scratch during each FixedUpdate, while the second example is changing the value of an existing one.

My question, quite simply, is does one have a performance advantage over the other? I realise that these examples will have a tiny performance overhead, but it would be good to know for more complex code where similar instructions might be running dozens of times simultaneously.

Thanks in advance for any insight anyone might have.

1 Like

This is a good example of why these things aren’t even worth thinking about.

In the first code snippet, movement is never used. Line 7 could just be deleted. The second code snippet probably never uses it either (it’s a global, so someone else might. But since it was local in the first snippet, it probably useless wastes space.) And, it appears to always set y to 0. So movement.x=h; movement.z=v; would be faster (but harder to read?)

Thinking about what might be a tiny speedup (or might be a tiny slowdown – it’s like all those shortcuts that aren’t really) makes you miss obvious stuff, like logic errors, or very slow code.

As for new, you can read about the tricks C# uses for very short-term garbage, when a new doesn’t make anything.

Vector3.Set runs in less than half the time. This is the code I used to benchmark:

using UnityEngine;
using System.Diagnostics;

public class Vector3SetBenchmark : MonoBehaviour
{
	public int runCnt = 100;
	int runNum;
	float dur;
	float dur2;

	void OnEnable ()
	{
		runNum = 0;
		dur = 0;
		dur2 = 0;
	}

	void Update ()
	{
		Vector3 v;
		Stopwatch stopwatch = Stopwatch.StartNew();
		v = new Vector3(1, 2, 3);
		stopwatch.Stop();
		dur += stopwatch.ElapsedTicks;
		Stopwatch stopwatch2 = Stopwatch.StartNew();
		v.Set(1, 2, 3);
		stopwatch2.Stop();
		dur2 += stopwatch2.ElapsedTicks;
		runNum ++;
		if (runNum >= runCnt)
		{
			print(dur / runNum + "\n" + dur2 / runNum);
			enabled = false;
		}
	}
}

I was curious about this to recently.

You can peek into the function using your IDE and see what the method actually does:

public void Set(float newX, float newY, float newZ)
{
  this.x = newX;
  this.y = newY;
  this.z = newZ;
}

It’s practically equivalent to setting the properties manually like this:

myVector.x = newX
myVector.y = newY
myVector.z = newZ

But much neater and nicer to read.

It’s good practice to avoid instantiating objects within frequently called methods like Update() or FixedUpdate() you generally create new objects in Awake() or in some cases Start()

In my case, I’m reading an 2D input axis vector using the Input-System package and converting it to a 3D direction.

/// Initially had this in my OnMovement function callback
_inputDirection = new Vector3(input.x, 0, input.y);

/// But changed it to this to avoid the unnessecary new Vector3(); 
_inputDirection.Set(input.x, 0, input.y);

well, by logic (i really dont know, but im going to try) i believe the second one would be faster, as it creates the variable once, and assigns it every update, whereas the first creates and assigns it every update.

keep in mind i dont really know, and this might only be a thousandth of a millisecond faster anyway, if it is at all

It depends on the internal Vector3.set() implementation.

Basically, if we assume that Vector3.set() doesn’t create a new object behind the scenes, than it will be faster.

Because when you use Vector3 name = new Vector3(1, 2, 3); you tell the compiler to create a new object and to assign it to the variable name. It doesn’t even matter if the Vector3 name is local or global, by using new you create a new object every time, therefore it requires a memory allocation every time. A lot of people think that if they declare a variable as global (i.e. have cashed the variable) than it’s already all fine and they are assured that now they could freely use it in Update() and FixedUpdate() loops. It’s not entirely true. If you use new keyword (even on the global variable) you create a new object and you trigger memory allocation in the heap every time.

So, assuming that Vector3.set() just changes the values of the existing object and there’s no new involved than it could be considered to be faster because it doesn’t require memory allocation.