3

In a simple movement script where body is gameObject.GetComponent<Rigidbody2D> (), movement is applied by this code

body.velocity = new Vector2 (10 * dir, body.velocity.y);

However in this one no movement (nor error) appears

body.velocity.Set (10 * dir, body.velocity.y);

I see no explanation in Unity documentation. Can you explain why body.velocity.x remains zero in the second case?

Programmer
  • 121,791
  • 22
  • 236
  • 328
Jan Turoň
  • 31,451
  • 23
  • 125
  • 169

1 Answers1

5

This is one of the mistakes people make while using Unity. You have to understand C# well to know what's really happening and why.

Here is why:

1.Rigidbody.velocity and Rigidbody2D.velocity are both types of Vector3 and Vector2.

2.Vector3 and Vector2 are both structs not class.

See struct vs class here for more info.

3.Rigidbody.velocity and Rigidbody2D.velocity are properties and uses a getter. This is means that it returns a copy of Rigidbody2D.velocity not the original variable or a reference of it because they are both structs as mentioned above.

See reference type and value type for more info on this.

4.When you call the Vector3.Set and Vector2.Set functions, you are calling that on a copy of a Vector3 and Vector2 not the actual or original Vector and this is due to #3.

If you really want to use the Set function on a Rigidbody create a different Vector variable you will be using to call that Set function on then assign the value to your Rigidbody.velocity.

For example,

Rigidbody2D body = null;
float dir = 4f;

Vector2 pos = Vector2.zero;

void YourFunction()
{
    pos.Set(10 * dir, body.velocity.y);
    body.velocity = pos;
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • 1
    Hmm. I could design a struct property with 10 members where most of them will be set independently by design. Then I aggregate it into every class in my project and pass the development to someone who I hate. – Jan Turoň Jan 14 '18 at 15:52
  • 1
    Lol I don't think Unity meant to make people suffer with that. They used `struct` for performance reasons because they want you to be able to `new Vector2` in a function without allocating memory. If they used `class` for this, your game would be slower if you use `new Vector2` in a function(especially the `Update`) function. Although, I think they should warn people when calling this function from a reference object otherwise a new Unity user would end up stuck on an issue like this one for days. – Programmer Jan 14 '18 at 16:05
  • I don't think that they should warn about this, it's a pretty basic concept of C# which should be learned as one of the first things of the language. – Galandil Jan 14 '18 at 16:52
  • 1
    @Galandil True. It's a C# thing but Unity is known for breaking with the standard sometimes. I think that they should make the `Set` function to perform work on the current `Vector` when called from a class. They did this for the `ParticleSystem` which uses `class`. They made it so that some of the Particle structs can be used to modify class/reference. See [this](https://stackoverflow.com/questions/40130332/understanding-the-struct-in-unity-particlesystem/40132652#40132652) post for example. It's not uncommon in Unity. – Programmer Jan 14 '18 at 17:07