Good way to keep track of fixed data? — Referenced Object or Static?

If you have a big list of variables that will never change — say for example, a price list that needs to be referenced — what is the better way to put this into the game? I have three different approaches in my head…

  1. Create a simple script of all the vars and attach it to a GameObject

  2. Create a simple script of all static vars, negating the need to attach or reference any GameObject

  3. Make a static class, which would include all the vars and wouldn’t require me putting ‘static’ in front of each variable (High possibility my assumption is incorrect here?)

3 Answers

3

I make a GameConstants class that holds true constants.

public class GameConstants {
  public const string PLAYER_TAG = "Player";
  public const float PRICE = 1.99;
  // ...etc
}

And then I reference it other scripts like:

public class Example {
  void Start() {
    GameObject.FindObjectsWithTag(GameConstants.PLAYER_TAG);
  }
}

I like this approach simply because my constants are in one, central location. You can further organize by splitting them into appropriately name Structs give better documentation such as…

public struct GameTags {
  public const PLAYER_TAG = "Player";
  public const MINI_MAP_CAMERA_TAGE = "MiniMap";
}


// referenced then like:

public class Something {
   void Start() {
      GameObject.FindObjectsWithTag(GameTags.PLAYER_TAG);
   }
}

It also has the benefit of not having to store a reference to the object holding the values if you just store it on a GameObject.

I second this approach, but the class and fields should be static so you don't have to create an instance of that class.

@Dracorat, No need--you can access them from the class/struct name directly just as you would a static variable, provided that it's public of course.

Doh. Constants "gotcha" - I forgot. I don't use constants often (I use variables that never change - largely because I create more complex types that need instantiation) In fact, if I recall correctly you can't even use the static keyword on a constant. So - good work. =)

I investigated Constants — hadn't heard of them before, but now it totally makes sense why Variables are named Variables! — I discovered they're not used in Javascript in Unity but I don't think that really makes much of a difference anyway unless you're trying not to accidentally modify them. I posted my own answer below — it's the simplest solution to what I was after! Thanks for the input though :)

I’ve had experience with two approached that seem to be robust.

Personally, I like using static classes for these sort of tasks, with public variables or public getters / setters:

public static GameSettings
{
    float m_timeScale;
    int   m_someOtherVariable;
    etc...
}

Another approach which I’ve seen being taken, is to create behaviour scripts and do a lookup on awake to resolve references. Personally, I like the first approach better, however this allows you to quickly swap in and out different data sets.

public GameSettings : MonoBehaviour
{
   public float m_price = 100.0f;
}

public SomeClassWhichUsesSettings : MonoBehaviour
{
   protected GameSettings m_gameSettings;

   void Awake()
   {
      m_gameSettings = FindObjectOfType( typeof( GameSettings ) ) as GameSettings;
   }
}

I posted my own answer below — it's the simplest solution to what I was after! Thanks for the input though :)

I wasn’t sure if my 3rd choice in my initial post would work but I just tested it and it works perfectly, so I think this is the most simple approach.

static class PriceList
{
	var costumePrice = 100;
}

Then access vis script using PriceList.costumePrice

Easy!

I must warn you however, that using "var" for simple types is an invitation to hard-to-track-down bugs. Var is inferred by the compiler and it might infer the value to something other than what you intended it. What if you wanted something to be a float and so you wrote var someVal = 1.3; - that would actually end up being a decimal. Maybe no big deal, maybe it is. I recommend that you use var only when you're dealing with Enumerations (such as with for-each and with LINQ).

I'm confused… So if I declared something as var someVal = 1.3; it would end up being declared as a float? But if I've set the value at 1.3 wouldn't that mean I wanted it to be a float?

By default, mixed numbers are "decimal" not float. Fixed number can be represented as float, decimal or double types. "var" allows the compiler to choose and while the compiler "usually" does great in this regard, when it doesn't do great, it can be a very difficult bug to track down.

I was talking about C# yes. And I didn't even realize that was a class member. (which wouldn't compile). Good catch. Sorry if I added confusion - to be clear, don't use var for primitive types in c# - you have to use var for UnityScript, of course.

Ah, thanks for clearing that up, @Bunny83 :)