The Attribute System is a framework designed to manage various values associated with entities within a game. These values can represent characteristics such as health, strength, agility, etc. The system provides a structured approach to handle these attributes, allowing for easy modification, tracking, and management throughout the game.

Attribute Component

The AttributeComponent is a component attached to gameobjects as a container of attributes and manages interactions with that value. It takes a list of AttributeSet objects as startup sets. When the component starts, it creates an AttributeValue for each ID within those sets. You interact with the component to deal with the values for each of those attributes. It will use the AttributeDefaultSource within the set to initialize each of those AttributeValue.

Diagram.drawio.svg

By hovering on the info icon, you will see detailed information about the attributes.

Attribute ID

AttributeID is an empty Scriptable Object that acts as a unique identifier for a specific attribute.

Attribute Value

AttributeValue is a Scriptable Object that holds the value and the modifiers of an attribute.

Attribute Set

The AttributeSet contains a set of AttributeID instances. It also contains an AttributeDefaultSource, which holds default values for each ID. Currently there are several built-in attribute set types:

Extending Attribute Set

When extending an AttributeSet you need to only deal with IDs. You access the values of those ID’s through a “context” parameter. (Check the MinMaxAttributeSet class for an example.)

public class MyAttributeSet : AttributeSet
{
	public AttributeID testID1;
	public AttributeID testID2;
	
	// When trying to Set an Attribute's Base Value through the SetBaseValue(ID, newBaseValue) method on the AttributeComponent, this function is called BEFORE.
	// The 'context' parameter will give you a way to access other attributes.
	// The 'id' parameter determines the attribute being modified.
	// The 'newBaseValue' is current base value going to be set to the attribute.
	//     Note that it is a ref parameters. Which means that it can be changed. Any change will be passed to other sets.
	public override void PreValueChange(IAttributeContext context, AttributeID id, ref float newBaseValue)
  {
		  //Always test against the set's ID's
      if (id == testID1)
      {
				// Pre Modification Checks and Changes for testID1
      }
      else if (id == testID2)
      {
				// Pre Modification Checks and Changes for testID2
      }
  }

	// When trying to Set an Attribute's Base Value through the SetBaseValue(ID, newBaseValue) method on the AttributeComponent, this function is called AFTER.
	// The 'context' parameter will give you a way to access other attributes.
	// The 'id' parameter determines the attribute being modified.
	// The 'oldBaseValue' parameter will give you the last base value the attribute had before modification.
  public override void PostValueChange(IAttributeContext context, AttributeID id, float oldBaseValue)
  {
      if (id == testID1)
      {
				// Post Modification Checks and Changes for testID1
      }
      else if (id == testID2)
      {
				// Post Modification Checks and Changes for testID2
      }
  }

	// This function is used by the AttributeComponent to check if the PreValueChange and PostValueChange functions should be called on this attribute.
  public override bool HasID(AttributeID id)
  {
      return id == testID1 || id == testID2;
  }

	// The function should return all IDs used for this attribute. It is used by the AttributeComponent when setting up the attributes.
  public override IEnumerable<AttributeID> GetIDs()
  {
      yield return testID1;
      yield return testID2;
  }
}

Default and Default Source

The AttributeDefaultSource is a Scriptable Object containing default values for each attribute ID. It holds a collection of AttributeDefault structs, each representing a default base value and modifiers for an attribute ID.

Modifier