Need an explanation on why exactly this works.

My Scriptable Object script:

       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 static List<int> testList = new List<int>();
        public static int listInt1;
        public  static void RecieveValue (int heroHP1)
        {
           listInt1 = heroHP1;
           Debug.Log(listInt1 + " is the value of listInt1 in the RecieveValue method.");
           testList.Add(listInt1);
           TestCount();
        }
        public static void TestCount()
        {
           Debug.Log(testList.Count + " is the current .Count of the testList.");
        }
    }

What i tried to do:
I have made multiple SO assets that i have attached to UI Buttons via OnClick in the inspector and made them pass the SO asset value to the RecieveValue method. Each button has its own unique SO asset made via SO script attached to it. I pass them to the method to add those values to the testList.

What happened:
Before adding the static modifier to the testList, listInt1, RecieveValue(), each button pressed would cause the RecieveValue to add the value to an individual list for each SO asset despite the RecieveValue method clearly adding the values to the testList.

What is happening now:
After adding the static modifier to the testList, listInt1, RecieveValue(), each button pressed adds its value to the one unified testList, instead of each having a list for themselves. This is exactly what i intended to do.
This solution suits my intent, as i only need to have one of each of those members.

What confuses me:
While i understand the purpose of the static modifier and what it does (taken from Microsofts C# reference: "Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object."), i don’t really understand how turning testList, listInt1, RecieveValue() into members that belong solely to the ListsScript type prevents SO values from being added to their individual testLists. I also don’t understand why even after assigning heroHP1 value to the listInt1 (before using a static modifier on the method and the list/instance variable) they have their own lists.

I understand that it might be a very basic question, but i’d rather try to understand why it solves the issue instead of leaving it as it is. Thank you for your answers.

Okay there would be a lot of basics to explain. You should read up on programming paradigms like what differentiates a Class/Type from an Object (Instance of a Class). That would be fundamental to being able to understand what “static” actually does. To complicate things even further you also have SOs with serialization.

Anyhow, I’ll try to give a short explanation here (full of bad analogies and simplifications) :wink:

So. Think of the Type (your class) as a blueprint (a plan made of paper with build instructions for a wooden shed). It itself does NOT contain any building material.

Now imagine you would want to build many sheds. It’s handy to have a blueprint (Type/Class). Now if you have made a real shed based on your blueprint then that’s your Instance/Object.

Now imagine you want all your new sheds to face north. It certainly would be useful to have a compass to achieve that. Now you will certainly not build a new compass for every shed. Instead you build one compass and store it together with your blueprint. How do you do that? Well, you tell everyone of your builders that your compass is STATIC and belongs to the blueprint. You may not separate those two. But if anyone currently making a shed needs it he can call out and ask if he can use it by saying “Blueprint.Compass”. Everyone knows there is just one compass and no matter from where it’s called it will always remain the same one.

In contrast every shed has it own walls, roof, a table and doors (your none static stuff). If a builder calls for a chair with “this.Chair” no one would go to the blueprint. It’s obvious he means the one right next to him within the shed he is working on. If you try to get a chair from the blueprint “Blueprint.Chair” everyone would look at you in a weird way 'cause obviously a real chair is not part of the blueprint.

As almost all improvised explanations this one is horrible. But I still hope it helps you understand.
Your “static” stuff is singular, there is just one. Everything else is local to your multiple instances within your buttons or ScriptableObjects.

Happy Coding!

1 Like

Thank you for your response, geo_! While you may consider your explanation to be “horrible”, it kind of helped me to understand how it works. I’ve went through many analogies: from animals and animal kingdoms to inventories, and yours seem to be the clearest one.
So let me confirm that i understood it all correctly (or at least semi-correctly): the reason my SO’s were each having a personal list was because they were using the testList as a “blueprint” instead of just having their values added to a unified list by essentially making the testList one with the “blueprint”. I’ll bring up an analogy that you might consider to be even worse than yours: let’s say that the SO’s are bolts (when they are passed to the method) and the class is a blueprint (actual physical blueprint). Without static, the bolts get their own boxes (one per each bolt type) and with static, the bolts go into a box that is physically attached to the blueprint itself rather than going to a box that is “created” for each bolt upon their “arrival” at the method.

Glad it was understandable. I like your bolts :slight_smile:
Yes that’s pretty much what happened, except that the box is created with the “new ListScript()” line, not at time of arrival (or more precisely it’s created when you create your SO via the context menu and then it is just serialized/deserialized but let’s skip that. Just adds too much confusion). Without static you filled a new list within every SO instead of using a “global” static one.
I’ll spare you the info that this “global” static data is not the ideal use of static (carrying around a blueprint with a lot of extras will slow you down). If you dare, have a look into “Singletons” (a concept which can fuel decades of dogmatic wars between programmers).

1 Like

Yeah, heard a thing or two about singletons. My current project is a small scale one, just to get a grasp of things, however i’ll be sure to try applying singletons and other programming patterns and reading more on when to use and not to use static. Thank you again for your explanation, that’s exactly what i wanted to know.

1 Like