1
\$\begingroup\$

Let's say I have a class A with many constants (over 20) and variables (also around 20). Class B represents a character so it has a lot of constants and variables representing various stats. Class C is GUI class and draw interface showing player his stats. I would like to have also classes for dialogs, items, quests, etc. Working with such a many variables is a lot of pain for me trying to manage it only in code.

How is that type of problems managed in game development? I'm doing an android game primarily so the performance cost should be get under consideration.

Example code that is really annoying and feels bad:

Label life, xp, gold, stamina, recovery, score; // etc. Label class is GUI text

void Start()
{
    life.text = Character.instance.Life.ToString();
    xp.text = Character.instance.XP.ToString() + "XP";
    gold.text = Character.instance.Gold.ToString() + "$";
    stamina.text = Character.instance.Stamina.ToString();
    recovery.text = Character.instance.Recovery.ToString();
    score.text = Character.instance.Score.ToString();
    // etc.
}

Or even:

int level, gold, experience, life; // etc.

void Start()
{
    level = STARTING_LEVEL; 
    gold = STARTING_GOLD; 
    experience = STARTING_EXPERIENCE; 
    life = STARTING_LIFE; 
    ...
}
\$\endgroup\$
2
\$\begingroup\$

Well I am not sure about good practises or standards here, but I do use Managers(Mostly Singletons) to manage certain aspects of my game. For example, I always have a GUIManager class which takes care of all the GUI related stuff for me. It has listener methods for every event, for example when player dies the player script calls OnPlayerDie() method on GUIManager, which pops up the message on screen. The change in health is also indicated via OnHealthChange() method.

In case you have too much data or UI elements, let other classes which are responsible for updating them, handle them. For example the life of player will be handled by Player class, the GUI Text or UILabel(if using NGUI) will still resides in GUIManager and will be accessed via Singleton calls by Player Class.

Reusing variables via managers is also a way to reduce number of variables.

\$\endgroup\$
0
\$\begingroup\$

Your example is exactly what is done, there's no magic way to make it go away, only to maybe to hide it. I don't think it's quite bad. You enter one line of code for each stat.

Another solution would be making some automatic code that would extract values from same named fields. Something like this:

class CharacterGui : BaseGui
{
    Label life;
    void Update(Character ch)
    {
        base.ExtractValues(ch); // life here would be auto assigned to value
    }
}
class BaseGui
{
    public ExtractValues(object o)
    {
        // use reflection to find matching fields and extract value from o,
        // call ToString() and assign it to label of the same name in your class
    }
}

But here you would need to have some kind of strict naming system, or use Attributes to mark fields:

class CharacterGui : BaseGui
{
    [Attribute("health")]
    Label life;
    void Update(Character ch)
    {
        base.ExtractValues(ch); // life here would be auto assigned to value from field "health" of ch
    }
}

Either way that seems a much more work and maintenance then just adding a single line of code. Those systems are usually put in place where there's a lot, and I mean a lot of code that will use it, think of million dollar companies with 100 programmers working on it. At those companies it actually can save a lot of time.

I would also suggest that you make your GUI classes not to rely on static vars, but rather take any instance of the class they want to display. That way when you change your mind later and decide that you want 2 characters on the screen, you can easily just reuse the code.

Label life, xp, gold, stamina, recovery, score; // etc. Label class is GUI text
void Update(Character ch)
{
    life.text = ch.Life.ToString();
    //...
}
\$\endgroup\$
0
\$\begingroup\$

I've decided to use dictionary for storing variables in my Character singleton class where key is string for example "life" and value is float value of the key.

Initializing the dictionary is made using readonly string and float arrays where I store in appropriate order string keys and float values (it can be done by using also enum to avoid some string related problems). Adding whole bunch of stats can be done in simple for loop. "Run-time" stats changes are made by using events since it fits rpg game mechanism.

Getting the values is very simple by using C# indexers feature:

    Dictionary<string, float> stats = new Dictionary<string, float>();
    public float this[string key]
    {
        get { return this.stats[key]; }
    }

And in practice it looks for example like this:

print(Character.instance["life"]);    // Will print character life value
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.