An instance variable doesn't change its value.

My Scriptable Object.

   using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
 
    [CreateAssetMenu (fileName = "Hero", menuName = "Create HeroValuesAsset")]
    public class HeroValues : ScriptableObject
    {
        ListsScript listsScript = new ListsScript();
 
        [SerializeField]
        private int heroHP;
        [SerializeField]
        private string heroName;
 
        public int HeroHP
        {
            get
            {
                return heroHP;
            }
        }
 
        public string HeroName
        {
            get
            {
                return heroName;
            }
        }
 
       public void PassValue()
       {
           int heroHP1 = HeroHP;
           listsScript.RecieveValue(heroHP1);
       }
    }

My ListsScript

   using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
 
    public class ListsScript
    {
        public int listInt1;
        public void RecieveValue (int heroHP1)
        {
           heroHP1 = listInt1;
           Debug.Log(listInt1 + " is the value of listInt1 in the RecieveValue method.");
        }
        public void TestValue()
        {
           Debug.Log(listInt1 + " is the current value of listInt1 instance variable.");
        }
    }

My TestScript

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScript : MonoBehaviour
{
    ListsScript listsScript = new ListsScript();
    void Start()
    {
    
    }

    void Update()
    {
        listsScript.TestValue();
    }
}

What is happening in my script:

I have made several ScriptableObject assets, each storing two individual values: heroHP and heroName. Those ScriptableObjects are assigned each to their own UI Buttons. The buttons are set to call the TestValue() OnClick in the inspector, with the object being the ScriptableObject asset (1 per button). OnClick() the button with the “assigned” SO passes the value of heroHP to the RecieveValue(heroHP1) in the ListsScript. Then, it assigns the value of heroHP1 to listInt1 instance variable.
On play mode, the button presses are registering the data passing to the method and i recieve the console message with the value and " is the value of listInt1 in the RecieveValue method." attached. Wonderful. However, the constantly updating listsScript.TestValue() call in the Update() of the TestScript MonoBehaviour remains at zero.

What am i trying to achieve:

I want the value of listInt1 of the ListsScript to change in accordance with whatever according to whatever value PassValue() passes.

Why am i trying to do this:

To use the “decoupled” value to add it to a List as adding the value currently as it is, results in each SO having their own individual list.

What have i already tried to solve this issue:

  • the solution above (directly changing the value of the field).
  • adding a getter and using RecieveValue(int heroHP1) as a setter, while making the listInt1 private and swapping the listInt1 in the TestValue() for the method (TestValue() still showing up zero).
  • using a constructor:
[code=CSharp]   using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
 
    public class ListsScript
    {
        public class ListIntValue
        {
           public int listInt1{ get; set; }

           public ListIntValue(int valueA)
           {
                 listInt1 = valueA;
           }
        }
        
        public void RecieveValue(int heroHP1)
        {
           var heroHPvar = new ListsScript(heroHP1);
           TestValue(heroHPvar);
           Debug.Log(heroHPvar + " is the value of listInt1 in the RecieveValue method.");
        }
        public void TestValue(ListsScript.ListIntValue heroHPvar)
        {
           Debug.Log(heroHPvar + " is the current value of listInt1 instance variable.");
        }
    }

which results into “ListsScript + ListIntValue is the current value of listInt1 instance variable.” shown in console on click with the TestScript MonoBehaviour disabled.

You seem to be struggling with the concept of value types vs. reference types. Since int is a value type, each time you pass it into a method as a parameter, you are creating a copy of that variable that exists only inside that method. Any changes the method makes to its parameter will not be reflected in the caller.

2 Likes

I have no idea what ListsScripts is, nor do I really understand what you’re trying to accomplish, but the one inside your ScriptableObject and inside your TestScript are two different instances that you’ve created with new.

So you can either use the list from the SO like this:

public class TestScript : MonoBehaviour
{
   public HeroValues heroValues; // drag an SO into this slot in the inspector

   void Update()
   {
       heroValues.listsScript.TestValue();
   }
}

Assign a local ListsScripts from the SO like:

public class TestScript : MonoBehaviour
{
   ListsScript listsScript;

   void Start()
   {
       HeroValues heroValues = // Get the SO from wherever you're trying to get it from
       listsScript = heroValues.listsScripts;
   }

   void Update()
   {
       listsScript.TestValue();
   }
}

Or make the whole thing static if there’s only ever going to be one:

public static class ListsScript
{
   private static int listInt1;

   public static void RecieveValue (int heroHP1)
   {
       listInt1 = heroHP1;
       Debug.Log(listInt1 + " is the value of listInt1 in the RecieveValue method.");
   }

   public static void TestValue()
   {
       Debug.Log(listInt1 + " is the current value of listInt1 instance variable.");
   }
}

… which you’d then use as ListsScript.ReceiveValue( ... ) instead of creating a local instance.

1 Like

No it doesn’t.
You are doing the opposite in your RecieveValue method:

heroHP1 = listInt1;

That sets the variable heroHP1 (which is the variable that you are passing into the method) to contain the value of listInt1 (which is the public variable).
If you want to assign the value of heroHP1 to listInt1, then you should be doing in your RecieveValue method:

1 Like

Thank you for the response, PraetorBlue! Struggling is the keyword. I understand the concept and the difference between those two, hence why i tried to “move” the value of the parameter passed in to the instance variable but thank you for the reminder.

Thank you for the response, GroZZleR! ListsScript is merely a class that recieves the input from OnClicking the UI Button. All i tried to do is to simply “decouple” the value that is input from the Button that has a SO OnClick object on it that passes the data to the method, as currently each SO is self-centered (e.g adding values to the List results in each SO having an individual list). Thank you for your input!

Thank you for the response, BaBiAGameStudio! Great, i spent tons of time on resolving something as trivial as this :face_with_spiral_eyes:. Yes, it solves the original issue, thank you very much! I’ll try to assign the variables properly next time instead of ignoring the order they are assigned in. All i needed to do is to simply

listInt1 = heroHP1;

in the RecieveValue method as of course it was zero: the value that got passed to the method was essentially “erased” by the zero value (the default value) of the listInt1 from outside the method. Now that i swapped them, it works as intended!

Thank you all for your quick answers! The issue is resolved :).