1

I need some help with understanding variable assignment with the C# language.

While scripting with Monodevelop for Unity, I assign RigidBody and Collider components (among others) of game objects to local variables. When I change those variables, either by calling their methods or changing their attributes, those changes are reflected in the original components. To make my point clearer I'll leave this pseudo-code below:

void someMethod(Rigidbody rb)
{
    Rigidbody localRigidBody;
    localRigidBody = rb;  //assigned external rb component to local rigidBody
    localRigidBody.velocity = 10.0f; //changes are reflected in the original rb object!
}

What confuses me are the changes in the game object which "contains" the rb Rigibody component. While I know this works, in mind it shouldn't work, because localRigidBody is a local variable, and changing the velocity of localRigidBody shouldn't change the velocity value of rb. Yet it changes, and it works, as the object with the rb component changes its velocity when i run my program. Can you explain me why?

Please inform me if my question isn't clarified and I'll try to express myself better.

Thank you.

kame
  • 20,848
  • 33
  • 104
  • 159
Dayman75
  • 176
  • 1
  • 9
  • Think of a variable as a pointer to a section of memory. The memory contains the fields and properties of the instance. If you have 2 variables, and you assign `a` to `b`, all you are doing is setting the pointers to the same section of memory. Therefore, if you alter the memory that they both point to, they will both have the same new value. – RB. Apr 15 '16 at 12:12
  • @RB so all variables in C# are pointers? Thank you for your answer. – Dayman75 Apr 15 '16 at 12:17
  • Your `localRigidBody` in this case will be a reference to that rigidbody, not a copy. Aside of some caching stuff etc. this can be seen as some quality of life because instead of doing something like `rb.AddForce` you would otherwise always have to write something like `GameObject.FindWithTag("Foo").GetComponent().AddForce()`. – Gunnar B. Apr 15 '16 at 12:18
  • you've discovered passing by reference. it's a good example of how software engineering is incredibly more difficult than one thinks. you wouldn't try to, say, do the structural engineering for a bridge, if you were a "hobbyist structural engineer" and decided to "get in to structural engineering". – Fattie Apr 15 '16 at 15:00

2 Answers2

2

Unity is passing that Rigidbody by reference. If you want a copy or clone of Rigidbody that is totally independent of the original object (rb) that was passed to your method you can use Instantiate:

void someMethod(Rigidbody rb)
{
    Rigidbody localRigidBody = Instantiate<Rigidbody>(rb);
    localRigidBody.velocity = 10.0f;
}

Otherwise in your original, as @RB stated, your localRigidBody is just an "alias" to the original rb variable as they both point to the same object (memory location).

See this SO question/answer to understand what passing by "reference" is: Passing Objects By Reference or Value in C#

Update:

What if I create a simple script where I declare a variable "int a = 10;" and then "int b = a" followed by "b=8". Will "a" change its value? Or is "b" an alias also?

Primitive data types are handled a little differently ;-) I would advice do some research on primitive vs. reference types, Microsoft has some great articles concerning this... your example:

Code:

int a = 10;
Console.WriteLine (a);
int b = a;
Console.WriteLine (b);
b = 8;
Console.WriteLine (a);
Console.WriteLine (b);

Output:

10
10
10
8
Press any key to continue...
Community
  • 1
  • 1
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • Thank you for your time :) Just one more question, if you have time: What if I create a simple script where I declare a variable "int a = 10;" and then "int b = a" followed by "b=8". Will "a" change its value? Or is "b" an alias also? Thank you. – Dayman75 Apr 15 '16 at 12:31
  • 1
    Quite some effort :) Thank you for your time. – Dayman75 Apr 15 '16 at 12:52
0

You just stumbled about an fundamental "feature" of most programming languages.

There are two ways to pass a variable around:

Pass by reference

In C# objects are passed by reference. This means whenever you are assigning an already existing Object (like your Rigidbody rb) to an variable (your localRigidBody), you are not creating a new Object. Instead your localRigidBody is just a reference to rb. If you want to create an independent copy of rb you need to "clone" it.

Pass by value

Types like int or double are passed by value. You will always get fresh and independent copy of parameter passed.

I would suggest you start with reading the msdn article

Sigma Bear
  • 931
  • 5
  • 7
  • Got it. Your answer did a terrific job. Thank you :) – Dayman75 Apr 15 '16 at 12:36
  • 1
    @Dayman75 i don't think anyone has actually answered the question. in unity **classes** are passed by reference. **structures** are passed as a value. this is an absolute basic of the milieu. – Fattie Apr 15 '16 at 15:02