Unity "static" variable?

I want to write a static function that will take a variable name I pass it, and check if that variable exists (the type is consistent), and if not, create it, and if so, will use that value.

So like DoSomething(string variableName, int variableSize)

And if I say DoSomething(apples, 2)
It'll look and see if int apples exists, and if not instantiate a int apples = 2.
And if this function runs again (in the same session) with the same passed name of "apples", it'll check again, and if int apples exist (it should) it'll just use that variable.

Is this where static comes in? Not sure how this works. Thanks in advance!

Comments

  • @Tuism,

    I'm not 100% sure of what you want to use it for, but from the description I think what you are looking for is a dictionary data structure. It can be static or non static depending on how you want to use it, though I would recommend you try to stay away from statics.

    http://csharp.net-informations.com/collection/dictionary.htm

    Unity's Player prefs works in a very similar way. You might even want to use that if you want the values to persist between sessions.

    https://answers.unity.com/questions/1325056/how-to-use-playerprefs-2.html
  • @rigormortis seems like I didn't explain properly, sorry - I don't need it to persist between sessions, I only need it to persist during a session.

    So I run this function, pass it "apple". It'll check if the int variable with the name "apple" exists, if it does, it uses it. If it doesn't, it creates it. That's it really.

    How do I pass a string into the function, and query if that name exists as a variable name?
  • Dictionaries supports a ContainsKey(key) method to check if the value already exists. You can check the c# documentation to see all the methods/properties that are supported.

    https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx

    In the documentation the "key" part is whatever you want to call your variables. "apples" in your example. The value would be the value that is associated with the key.

    Maybe you should explain a little more about what it is you want to do though. Rereading your initial post you mention that you want it to look to see if "int apples" exist, which is checking the name and type. This is not something directly/easily done with dictionaries.
    Thanked by 2mattbenic Tuism
  • With what you're saying with Dictionaries, you mean I'd have to create a list and check against the list, rather than check "if this variable exists anywhere"? I guess I can do that.

    So what I'm trying to do is to create a function that I can call once, checks if an variable of int type by that name exists. If yes, use that variable. If not, create that variable, then use it.

    More detailed description of my function:

    void ControlledRandom (string varName, int varRange)
    with the varName it stores a list of varRange number of elements, and runs a Random.Range call against it, and removes an element from the list whenever I call it. And this ensures a controlled random which will eventually calls every element in the range of random instead of maybe getting ten zeros in a row.
  • You are talking about a kind of Object Pool.

    Object Pooling - Unity

    Essentially you want to do something like that, but instead of an object you contain a Dictionary of <string, int> or whatever and when you access something you can either create it or remove it.
    Thanked by 1Tuism
  • Hmmmmmm, I still feel like I'm missing something in what you want to achieve. The way I understand it so far is that you want to be able to randomly select from a series of values, but only select the value once. You also want to be able to add values to the series as well as be able to manage multiple series of values.

    Is that correct?
    Thanked by 1Tuism
  • @Thelangfordian yes actually that sounds right, I've done object pooling before, I guess I'll just use those principles. And looks like dictionaries is it. I was hoping I can arbitrarily look up whether an int variable by a given name exists. I guess that's just too arbitrary for unity :P

    @Rigormortis yes - I want to do all that from one function without having to setup the whole thing first - I already have that functionality, I can already do that, but I want to do that without having to setup a variable first manually.
  • edited
    I was hoping I can arbitrarily look up whether an int variable by a given name exists. I guess that's just too arbitrary for unity :P
    I'm pretty sure that's too generic for any programming language. :P

    But ok, I understand what you are aiming to do now. A dictionary will probably be your best bet. If you want to access it from anywhere in the project you are going to have to do some boiler plate code do provide all the functionality you want though.

    As an example, you will probably need 2 methods for getting and adding values to the dictionary.

    public void AddValues(string rangeName, List<int> values)
    {
       // Adds a value to the range if it exists, otherwise it adds the range to the dictionary and then adds the values.
    }
    public int GetRandomValue(string rangeName)
    {
       // Gets a random value from the range. If the range doesn't exist returns -1 by default(or something).
    }


    Your dictionary declaration will then look something like this:
    Dictionary<string<List<int>> valueRanges;


    There are quite a few ways that you could go about this though, so you'll have to do some reading/experimenting to see what works best. Again though, I would recommend you stay away from using statics. They have their place, but often times create unnecessary problems.
  • edited
    I think this code will do what you need.

    public static Dictionary<string, List<int>> MyDictionary = new Dictionary<string, List<int>>();
    
        public static void AddValue(string key, int value)
        {
            List<int> values = null;
            if (!MyDictionary.TryGetValue(key, out values))
            {
                values = new List<int>();
                MyDictionary.Add(key, values);
            }
    
            values.Add(value);
        }
    
        public static int GetValueAndRemove(string key)
        {
            int result = int.MinValue;
    
            List<int> values = null;
            if (!MyDictionary.TryGetValue(key, out values))
                return result;
    
            if (values.Count == 0) return result;
    
            int rnd = UnityEngine.Random.Range(0, values.Count);
            result = values[rnd];
    
            values.RemoveAt(rnd);
    
            return result;
        }
        //test it here
        void Start ()
        {
            AddValue("test", 0);
            AddValue("test", 10);
            AddValue("test", 20);
            Debug.Log(GetValueAndRemove("test"));
            Debug.Log(GetValueAndRemove("test"));
            Debug.Log(GetValueAndRemove("test"));
            Debug.Log(GetValueAndRemove("test"));
        }
  • edited
    I understood his initial question a little differently to be:

    public static class ValueHelper
    {
      public static Dictionary<string, int> ValuesDictionary = new Dictionary<string, int>();
    
      public static void DoSomething(string key, int value)
      {
        int temp;
        if (ValuesDictionary.TryGetValue(key, out temp)) // If it already has a value for this key
          ValuesDictionary[key] = value; // Then update the old value
        else
          ValuesDictionary.Add(key, value); // Else just create a new item with the value
      }
    
      public static int GetValue(string key)
      {
        int temp;
        if (ValuesDictionary.TryGetValue(key, out temp)) // If this key exists
          return temp; // Then return the value we have
        else
          return -1; // Or throw an error or something
      }
    }

    And then from anywhere (any other class you have) you can call ValueHelper.DoSomething ("Apple", 2);

    Or, @Tuism, if you have a finite list of items that you want to track (i.e. apple, peach, etc.), then I highly recommend using an enum for the key. String (as in using "apple") are prone to error (typo's and such).

    public static class ValueHelper
    {
      public static Dictionary<eGameValues, int> ValuesDictionary = new Dictionary<eGameValues, int>();
    
      public static void DoSomething(eGameValues key, int value)
      {
        int temp;
        if (ValuesDictionary.TryGetValue(key, out temp)) // If it already has a value for this key
          ValuesDictionary[key] = value; // Then update the old value
        else
          ValuesDictionary.Add(key, value); // Else just create a new item with the value
      }
    
      public static int GetValue(eGameValues key)
      {
        int temp;
        if (ValuesDictionary.TryGetValue(key, out temp)) // If this key exists
          return temp; // Then return the value we have
        else
          return -1; // Or throw an error or something
      }
    
      public enum eGameValues
      {
        Apples,
        Bananas,
        Peaches
      }
    }
    Thanked by 1critic
  • edited
    roguecode said:
    I understood his initial question a little differently to be:
    I thought the same until he said this.
    Tuism said:

    void ControlledRandom (string varName, int varRange)
    with the varName it stores a list of varRange number of elements, and runs a Random.Range call against it, and removes an element from the list whenever I call it. And this ensures a controlled random which will eventually calls every element in the range of random instead of maybe getting ten zeros in a row.
    Which now points me to believe that it could be achieved like this, using my previous code.
    public static void InitializeKey(string key, int range)
        {
            for (int i = 0; i < range; i++)
                AddValue(key, i);
        }


  • Tuism said:
    Is this where static comes in?
    When something is static it means that is is allocated statically. This means its lifetime is the entire length of the game and will no be garbage collected. If you have a class that has a static member, that member will be allocated once (when the application starts) and anything referencing/modifying that member will reference the same member. For example:

    public class TestClass1
        {
    		private static int _internalStatic = 1;
    
    		public TestClass1()
    		{
    			Console.WriteLine("Current val: {0}", _internalStatic++);
    		}
        }

    If I instantiate 3 of this class, this is the output:

    Current val: 1
    Current val: 2
    Current val: 3
    Tuism said:
    I was hoping I can arbitrarily look up whether an int variable by a given name exists. I guess that's just too arbitrary for unity
    This is exactly what Dictionaries are used for (as mentioned above). As for what you're trying to achieve, thats still a little vague but hopefully you have enough to go on now.

    As a side note to everyone, not sure if this is true in Unity, but in C# you dont have to call
    dictionary.Add(key, value)

    You can simply just do:
    dictionary[key] = value


    This will create the entry, or overwrite it if it exists.
  • Thanks all for your inputs, I haven't really looked into this problem much right now as I'm working on other bits, but when I look into this again I'm sure this will be invaluable, and I'll come back and let ya'll know if I understood this dictionary stuff or not... -_-|||
    Thanked by 1critic
  • I was hoping I can arbitrarily look up whether an int variable by a given name exists. I guess that's just too arbitrary for unity :P
    Almost sounded like you wanted to go to the dark side of reflection...
    Thanked by 1critic
  • Just my 2 cents.. You could also use ExpandoObject (or the "dynamic" type). Although this just implements IDictionary<string, object> underneath.

    You can add properties or methods to it at run-time.

    This is part of C# 4.0 and up.
  • Dynamic makes me feel uneasy.
  • I agree. The dynamic type is pretty awesome and has some uses, but it makes debugging extremely difficult at times. I wouldn't recommend using them unless you really know what you are doing, and even if you do try something else first.
Sign In or Register to comment.