How to change variables that were the origins for parameters of a function with parameters.
I have a reload function that looks like this:
 void Reload (int mag, int magsize, int ammo )
 {
    int missing_ammo = magsize - mag;
    ammo -= missing_ammo;
    mag = magsize;
 }
 
               And when it gets called by different weapons...
 Reload(mag_plasmagun, magsize_plasmagun, ammo_plasmagun);
 
               ...the actual plasmagun values don't change after completing the reload.
I've found some info on the subject that states, that variables from which all the function parameters originate are not changed when those parameters are changed. Basically the parameters are only clones of the originals.
So do I need to make a separate reload for every weapon? Or is there a way to change the originals from a function with parameters?
Answer by NoseKills · Aug 20, 2016 at 02:18 AM
This doesn't have anything to do with functions specifically.
It's just that value types get passed by value and reference types by reference. See @Bunny83's correction in the comments
 // value types
 int a = 0;
 int b = 99;
 a = b;
 b = 100;
 //a == 99, b == 100. a and b are still separate. Just the value of b got assigned to a
 
 // reference types
 GameObject a = new GameObject("0");
 GameObject a = new GameObject("99");
 a = b;
 b.name = "100";
 //a.name == 100, b.name ==100. a and b reference the same object
 
 
               You have to make a reference type (a class) to store and pass around the values you want to change when reloading a gun.
Just arrange your classes like they are in real life: A "Magazine" class that has "maxAmmoCount" and "ammoLeft" that decreases when you fire. A gun class that has a magazine variable. Your gun's reload method takes in the new clip as a parameter and does whatever you want with the old clip and the ammo left in it. Maybe a "MagazineBelt" class with a collection of Magazines List<Magazine> where the clips get taken from.
So this doesn't work
 class Gun{
    public int ammo;
 }
 
 class ReloaderClass{
    public static void Reload(int ammo){
       ammo +=30;
    }
 }
 ...
 Gun gun = new Gun();
 ReloaderClass.Reload(gun.ammo);
 
 
               But this works
 public static void Reload(Gun gun){
       gun.ammo +=30;
 }
 Reload(gun);
 
              That's actually a common misinterpretation. All method parameters are actually passed by value unless you use ref / out parameters. The concept of "passing" seems to confuse most people. Variables of reference types are not passed by reference, they are copyied like any other variable. You just have to understand what is the "content" / value of the variable. The "value" of a reference type variable is the reference. This reference is copyied onto the stack. The method can not change the "value" of the passed variable unless the parameter is a ref / out parameter.
Of course you can use a passed reference to access the actual object behind the reference and modify the object, but you can't replace it.
 class FooBar
 {
     public string text = "Hello World";
 }
 
 void Some$$anonymous$$ethod(FooBar obj)
 {
     // use the passed reference to modify the object
     obj.text = "new string";
     // this will not change the variable that got passed to the method
     obj = new FooBar();
     obj.text = "You never see this".
 }
 
 FooBar myVariable = new FooBar();
 // the "value" of myVariable gets passed by value
 Some$$anonymous$$ethod(myVariable);
 Debug.Log(myVariable.text); // prints "new string".
 
                  Now the same thing with a ref parameter:
 void SomeOther$$anonymous$$ethod(ref FooBar obj)
 {
     // use the passed reference to modify the object
     obj.text = "new string";
     // this "will" change the variable that is passed to the method
     obj = new FooBar();
     obj.text = "You should see this".
 }
 
 FooBar myVariable = new FooBar();
 // Now the variable itself is passed by reference, not just it's value.
 SomeOther$$anonymous$$ethod(ref myVariable);
 Debug.Log(myVariable.text); // prints "You should see this".
 
                  Furthermore:
 FooBar myVariable = new FooBar();
 // copy the value of the variable into a new variable. Both will contain the same reference
 FooBar mySecondVar = myVariable; 
 // SomeOther$$anonymous$$ethod will replace the old reference with a reference to a new object
 SomeOther$$anonymous$$ethod(ref myVariable);
 if (myVariable == mySecondVar)
     Debug.Log("This never prints");
 
                  Likewise you can pass value type variable by reference and modify it inside the method:
 void CalculateTheAnswer(ref int paramValue)
 {
     paramValue = (2 * 3 * 5 * 7) / paramValue;
 }
 
 int answer= 5;
 CalculateTheAnswer(ref answer);
 Debug.Log("The answer is: " + answer); // prints "The answer is: 42"
 
                 Yeah. $$anonymous$$y example and the explanation of it wasn't accurate. I'll leave it there with an edit though, since reading both of these might be useful for more people - and the "how to do the reloading" bit is still valid.
Your answer
 
             Follow this Question
Related Questions
Can't get to work a non behaviour constructor with random generated variables 1 Answer
Advance Colision Detection 1 Answer
Obstacle Spawner Efficiency 0 Answers
Creating an object using a prefab, with parent, text etc.. 1 Answer
Trying to Invoke Void when Void has Stuff in Parameters - Easy Question 1 Answer