In my game, I have properties that represent values associated with characters. This could be, for instance, a player’s health, their stamina, energy and so on. These values can be modified through external sources, for instance through buffs, talents, curses, passive abilities and so on.
I use SO instances to define what properties exist instead of using a C# enumeration:
public abstract class PropertyData<T> : ScriptableObject
{
[SerializeField]
private T defaultValue = default;
[SerializeField]
private int identifier = -1;
public T DefaultValue => defaultValue;
public int Identifier => identifier;
}
Different types of properties
[CreateAssetMenu]
public class IntegerPropertyData : PropertyData<int> {}
[CreateAssetMenu]
public class FloatPropertyData : PropertyData<float> {}
[CreateAssetMenu]
public class BooleanPropertyData : PropertyData<bool> { }
and so on, so far only primitive types.
Each character in my game has property providers which keep track of all properties that a character currently has:
[Serializable]
public class Property<T>
{
[SerializeField]
private T value = default;
[SerializeField]
private PropertyData<T> data;
public T Value => value;
public int Identifier => data.Identifier;
}
public abstract class PropertyProvider<T> : MonoBehaviour
{
[SerializeField]
private Property<T>[] properties = null;
public Property<T> Get(int identifier)
{
Property<T> property = null;
for (int index = 0; index < properties.Length; index++)
{
if(properties[index].Identifier == identifier)
{
property = properties[index];
}
}
return property;
}
}
As well as different types here
public class FloatPropertyProvider : PropertyProvider<float> {}
and so on.
So far, so good. Now to come to my question, when I have external objects that somehow work with these properties, how can I determinate the type of a property and locate the correct property provider?
If you imagine that PropertyData<T>
inherits from a non-generic PropertyData
and objects only reference an object of type PropertyData
, don’t I lose the type information? Something like this:
public class PropertyModifierData : ScriptableObject
{
[SerializeField]
private PropertyData targetProperty;
}
Is there a design pattern to resolve this issue or some other neat advice on how to deal with this issue? Do I have to make all my objects interacting with properties generic, too?
// data for a modifier that modifies a property of type T.
public abstract class PropertyModifierData<T> : ScriptableObject
{
[SerializeField]
private PropertyData<T> targetProperty;
}
public class FloatPropertyModifierData : PropertyModifierData<float> {}