I’ve done something that works, but I wonder if it is the best way to do it?
I’ve created a class Stat.cs
[System.Serializable]
public class Stat {
// Base Value
public float BaseValue;
// Used by StatAttribute to know if stat default value has been set
[SerializeField]
[HideInInspector]
private bool m_statAttributeInitialized = false;
public Stat()
{
BaseValue = 0f;
}
public Stat(float _startingValue)
{
BaseValue = _startingValue;
}
}
So I could basically have something like
public Stat Health = new Stat(100);
to set the default health of my character to 100;
Where this get a bit trickier, is that I also use that class as a modifier. A character as a list of Damage modifier base on the damage type (let say fire, cold, lightning, physical, etc.)
So I have this:
public Stat[] DamageTypesModifier = new Stat[(int)DamageType.Types.Count];
But I want each stat to be initialized with a BaseValue = 1. I didn’t want to create an editor script for my Character.cs just for that array. I could also want to initialize other Stat array in various class and making an editor script for each of them would be annoying.
So I created an StatAttribute.cs
public class StatAttribute : PropertyAttribute
{
public readonly float BaseValue;
public StatAttribute(float _baseValue)
{
this.BaseValue = _baseValue;
}
}
and an associated drawer. Basically, it checks if my init flag is true, if not, it sets the BaseValue.
[CustomPropertyDrawer(typeof(StatAttribute))]
public class StatAttributeDrawer : PropertyDrawer
{
StatAttribute statAttribute { get { return ((StatAttribute)attribute); } }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty baseVal = property.FindPropertyRelative("BaseValue");
SerializedProperty init = property.FindPropertyRelative("m_statAttributeInitialized");
if (!init.boolValue)
{
init.boolValue = true;
baseVal.floatValue = statAttribute.BaseValue;
}
EditorGUI.BeginProperty(position, label, property);
baseVal.floatValue = EditorGUI.FloatField(position, label, baseVal.floatValue);
EditorGUI.EndProperty();
}
}
Now I can do this, and they will all be set to 1 by default. I can also edit them before/during runtime without having the default value being set each time.
[Stat(1f)]
public Stat[] DamageTypesModifier = new Stat[(int)DamageType.Types.Count];
This avoided me to create a StatModifier class that only override Stat class with a default constructor that set BaseValue =1; This can also be used to initialize a Stat array with another value than 1.
Is there a better way to do this?