Stats 02: Generic Collection

In this section we extend our RPGStat class and our RPGStatCollection classes. In the base stat class we add additional properties that will simplify adding features we’ll be adding in the future. In the stat collection we will be modifying our method into generic version to easily allow us to accept any stats that inherit from our RPGStat class.

This post is an old implementation and should be only used as a reference. This post maybe updated or replaced in the future.

Updating the base Stat

The main update to the is we will be changing how the StatValue property behaves along with a few name changes to help clarify the purpose of each property and variables.

using UnityEngine;
using System.Collections;

public class RPGStat {
    private string _statName;
    private int _statBaseValue;

    public string StatName {
        get { return _statName; }
        set { _statName = value; }
    }

    public virtual int StatValue {
        get { return StatBaseValue; }
    }

    public virtual int StatBaseValue {
        get { return _statBaseValue; }
        set { _statBaseValue = value; }
    }

    public RPGStat() {
        this.StatName = string.Empty;
        this.StatBaseValue = 0;
    }

    public RPGStat(string name, int value) {
        this.StatName = name;
        this.StatBaseValue = value;
    }
}

The changes to notice are that we renamed the variable _statValue to _statBaseValue and the property from StatValue to StatBaseValue. Then we added another property named StatValue. The reason behind these changes is that the StatBaseValue of the stat will be the value that all later buffs, items, and other modifiers will use in calculating their values that will be added onto the stat. The StatValue will be the total value of the stat with all the buffs, items, and other modifiers added together with the StatBaseValue.

The other main change is that the StatValue and the StatBaseValue properties are set to virtual. This small change will allow future classes that inherit from the RPGStat to change how the values of the stat is calculated.

Updating the Stat Collection

In the RPGStatCollection class we will make a small change to how the GetStat, CreateStat, and the CreateOrGetStat methods are written to allow the collection to add classes that inherit from the RPGStat class without having to add additional methods to access and create the derived stats.

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

public class RPGStatCollection {
    private Dictionary _statDict;

    public RPGStatCollection() {
        _statDict = new Dictionary();
        ConfigureStats();
    }

    protected virtual void ConfigureStats() {

    }

    public bool Contains(RPGStatType statType) {
        return _statDict.ContainsKey(statType);
    }

    public RPGStat GetStat(RPGStatType statType) {
        if (Contains(statType)) {
        return _statDict[statType];
        }
        return null;
    }

    public T GetStat(RPGStatType type) where T : RPGStat {
        return GetStat(type) as T;
    }

    protected T CreateStat(RPGStatType statType) where T : RPGStat {
        T stat = System.Activator.CreateInstance(T);
        _statDict.Add(statType, stat);
        return stat;
    }

    protected T CreateOrGetStat(RPGStatType statType) where T : RPGStat {
        T stat = GetStat(statType);
        if (stat == null) {
            stat = CreateStat(statType);
        }
        return stat;
    }
}

In our CreateStat method we use the class within the System namespace named Activator. This class will aid in the creation of an instance of any class given the type of the class. This allows us to create a instance of any class that inherits from the RPGStat without knowing it within the collection.

Updating the Default Stat Collection

Finally we update our default stat collection to use the new generic versions of the collection’s create methods.

using UnityEngine;
using System.Collections;
public class RPGDefaultStats : RPGStatCollection {
    protected override void ConfigureStats() {
        var health = CreateOrGetStat<RPGStat>(RPGStatType.Health);
        health.StatName = "Health";
        health.StatValue = 100;

        var mana = CreateOrGetStat<RPGStat>(RPGStatType.Mana);
        mana.StatName = "Mana";
        mana.StatValue = 2000;
    }
}

Note* In order to easily change which class controls how the stat is handled, you simply need to change the stat class being passed as the generic parameter to the create methods. Also changing the variable’s type that holds the created stat from RPGStat to var will automatically updated the variable to the type of the newly created stat.

Running the RPGStatTest script at this point should display the same result as the previous section, since we just changes some of the methods for setting up the stats and did not change anything else functionality wise.


3 thoughts on “Stats 02: Generic Collection”

  1. I know it’s been a year and not sure if you are still watching this blog, but I have an error at the end of RPGStatCollection. When we made the generic <T> here : protected T CreateOrGetStat<T>(RPGStatType statType) where T : RPGStat{
    T stat = GetStat<T>(statType);
    if(stat == null) {
    stat = CreateStat(statType);
    }
    return stat;
    it is saying that the stat = CreateStat(statType); cannot be inferred from usage and to try to type arguments specifically. Any thoughts?

    I love the tutorials I am new to C# and learning a ton about it, THANKS!

  2. Opps I pasted wrong version the problem is here :

    protected T CreateOrGetStat<T>(RPGStatType statType) where T : RPGStat{
    T stat = GetStat<T>(statType);
    if(stat == null) {
    stat = CreateStat<T>(statType);
    }
    return stat;

    1. GRRR nevermind I found it I forgot to change a RPGStat to T above…thanks again for the tutorials I hope you are doing well and keep on rocking.

Leave a Reply

Your email address will not be published. Required fields are marked *