Item Set & Rules
The Item Set, Rules and Manager are responsible for choosing what items get to be equipped together. Such as choosing to equip the Sword and Shield together.
ItemSets represent a set of CharacterItems that can be equipped at the same time. The ItemSetManager is the component responsible for switching which ItemSets are active. When a new item is added to the character the ItemSetRules automatically creates ItemSets by matching any valid permutations of CharacterItems. More than one ItemSet can be active at the same time by using multiple ItemSetGroups.
Item Set Manager
The ItemSetManager manages what ItemSet gets activated and when. The Equip Unequip Item Ability works with the ItemSetManager to decide what item gets equipped. At edit time the ItemSetManager shows the ItemSetGroups with their ItemSetRules.
At runtime the ItemSetManager shows the ItemSets and their state:
The colored dot next to the ItemSet name shows the current state of the ItemSet:
- Green: Active.
- Yellow: Enabled.
- Red: Invalid or Disabled.
On Add Item Update Item Sets Options
Choose if and when the item sets get updated when a character Item is spawned or removed on the character.
- Immediately: The ItemSet should be updated immediately.
- ScheduleToLateUpdate: The ItemSets should be updated within LateUpdate.
- Manual: The ItemSets should be updated manually with the UpdateItemSets method.
The ItemCollection containing all the items the character can equip. It is mainly used to initialize the ItemTypes on awake and checking the ItemType categories.
Item Set Group
The Item Set groups containing the rules to create ItemSets at runtime.
Update the ItemSets
Update the ItemSets manually:
Get a specific ItemSet
Get first matching ItemIndentifier ItemSet:
ItemSet itemSet = m_ItemSetManager.GetItemSet(itemIdentifier, groupIndex, checkIfValid);
Get ItemSet matching list of ItemIndentifier (ordered by slot):
ItemSet itemSet = m_ItemSetManager.GetItemSet(itemIdentifierList, groupIndex);
Get ItemSet by state name:
ItemSet itemSet = m_ItemSetManager.GetItemSet(itemSetName, groupIndex);
Get ItemSet by index:
ItemSet itemSet = m_ItemSetManager.GetItemSet(itemSetIndex, groupIndex);
Get active and next ItemSet
Get active ItemSet:
ItemSet itemSet = m_ItemSetManager.GetActiveItemSet(groupIndex);
Get active ItemSet index:
int itemSetIndex = m_ItemSetManager.GetActiveItemSetIndex(groupIndex);
Get next ItemSet:
ItemSet itemSet = m_ItemSetManager.GetNextItemSet(groupIndex);
Get next ItemSet index:
int itemSetIndex = m_ItemSetManager.GetNextItemSetIndex(groupIndex);
Equipping and Unequiping
Try equipping an ItemSet using its main state name:
bool success = m_ItemSetManager.TryEquipItemSet(itemSetName, groupIndex, forceEquipUnequip, immediateEquipUnequip);
Try equipping an ItemSet:
bool success = m_ItemSetManager.TryEquipItemSet(itemSet, forceEquipUnequip, immediateEquipUnequip);
Equip or unequip an item using the first matching ItemSet:
m_ItemSetManager.EquipUnequipItem(itemIdentifier, equip, groupIndex, forceEquipUnequip, immediateEquipUnequip);
Equip an Item using the first matching ItemSet:
m_ItemSetManager.EquipItem(itemIdentifier, groupIndex, forceEquipUnequip, immediateEquipUnequip);
Unequip an Item using the first matching ItemSet:
m_ItemSetManager.UnequipItem(itemIdentifier, groupIndex, forceEquipUnequip, immediateEquipUnequip);
Item Set Groups
The ItemSetManager contains a list of ItemSetGroups, each with their own rules and sets. A Category is used to identify the ItemSetGroups. Item Abilities such as EquipUnequip will use that Category to reference the relevant group.
The rules within the ItemSetGroup do most of the work, but the ItemSetGroup does have some useful functions to get information about the ItemSets and their rules. The ItemSetRule list within the group can be changed at runtime. Strategically adding and removing ItemSetRules is a great way to ensure a clean organization. It is also the best way to add custom ItemSetRules from MonoBehaviours instead of scriptable objects since the IItemSetRule int
Serialized Item Category
The item CategoryBase to identify the ItemSetGroup.
Starting Item Set Rules
The starting array of ItemSetRules. The actual list can be changed at runtime.
Get ItemSetRule and ItemSets
Get the ItemSetRule from an ItemSet:
IItemSetRule itemSetRule = m_ItemSetGroup.GetItemSetRule(itemSet);
Get all ItemSets created by a rule:
ListSlice<ItemSet> itemSets = m_ItemSetGroup.GetRuleItemSetList(itemSetRule);
Add and remove rules at runtime
Insert an ItemSetRule at a specific index:
Add an ItemSetRule:
Remove an ItemSetRule:
Set the list of ItemSetRules:
Item Set Rule
ItemSetRules are used to create the ItemSets given a list of Items. Usually the ItemSetRules are notified to create and delete ItemSets as items are added to and/or removed from the character.
For example an ItemSetRule cannot create an ItemSet with a sword in Slot 1 if the CharacterItem has it defined as Slot 0. If an Item can be equipped in both slots then the CharacterItem must be created for each slot.
There are many types of Item Set Rules. They can be ScriptableObjects or they can be assigned to an ItemSetGroup at runtime by inheriting the IItemSetRule interface. The built-in ItemSetRules can be created by going to the project window and right-clicking Create -> Opsive -> Ultimate Character Controller -> Inventory.
The built-in ItemSetRules are:
The simplest ItemSetRule to get started quickly. It will create ItemSets for all items and assign it the relevant slot by checking the CharacterItem. It is called “Individual” since it creates ItemSets with a single item inside.
The list of exceptions can be used to exclude certain items from getting their ItemSet automatically created. This way other ItemSetRules can be used to define how they can be combined with other items.
The classic ItemSetRule which defines the exact item combination wanted.
The category ItemSetRule allows creating item sets by combining items by their categories.
In this example where Slot 0 corresponds to the Magic category and Slot 1 corresponds to the nothing category it will create multiple ItemSets all with magic items in slot 0. A category ItemSetRule can be used with a left hand in slot 1 and right hand in slot 0 allowing any item combination for items inheriting those categories.
In some cases you may want to share the same rules across multiple characters. This rule combines other rules inside a single ScriptableObject using a list of ItemSetRules.
The ItemSetGroup will ensure each ItemSet is mapped to the inner ItemSetRule.
You can make your own ItemSetRule. This is a great way to dynamically create ItemSets depending on the game state. There are three main ways to create a new rule:
- Inherit the ItemSetRule ScriptableObject which already comes predefined and can be used to easily create ItemSetRules to assign to the ItemSetGroup at edit time.
- Inherit ItemSetRuleBase ScriptableObject to have a ScriptableOobject that can be assigned to the ItemSetGroup at edit time.
- Inherit IItemSetRule interface to a class or MonoBehaviour and assign it to an ItemSetGroup at runtime.
Inheriting ItemSetRule is a bit easier as the functions to override simply returns booleans. It is also what is used for Individual, Category and ItemType ItemSetRules.
/// <summary> /// Does the character item match this rule. /// </summary> /// <param name="itemSetRuleStreamData">The item set rule stream data.</param> /// <param name="currentPermutation">The current item permutation so far.</param> /// <param name="characterItem">The character item to check.</param> /// <returns>True if the character item matches this rule.</returns> public abstract bool DoesCharacterItemMatchRule(ItemSetRuleStreamData itemSetRuleStreamData, ListSlice<IItemIdentifier> currentPermutation, CharacterItem characterItem); /// <summary> /// Can the slot be empty for this rule. /// </summary> /// <param name="slotID">The slot ID to check.</param> /// <returns>True if it can be empty.</returns> protected abstract bool CanSlotBeNull(int slotID);
Inheriting IItemSetRule or ItemSetRuleBase gives the most flexibility, but requires more thought. Two functions must be overridden:
/// <summary> /// From the Item Set Rule Stream Data return the next item set state info. /// </summary> /// <param name="itemSetRuleStreamData">The item set rule stream data.</param> /// <returns>Return the item set state info.</returns> public abstract ListSlice<ItemSetStateInfo> GetNextItemSetsStateInfo(ItemSetRuleStreamData itemSetRuleStreamData); /// <summary> /// Returns if an item set is valid for the allowed slots mask. /// </summary> /// <param name="itemSet">The item set to check.</param> /// <param name="allowedSlotsMask">The allowed slots mask.</param> /// <returns>Returns true if the item set is valid.</returns> public abstract bool IsItemSetValid(ItemSet itemSet, int allowedSlotsMask);
The GetNextItemSetsStateInfo function takes in the current state of the ItemSets for that were created by this rule. It returns a list of ItemSets to add, keep or remove.
From there the ItemSetGroup and the Manager will ensure the ItemSets are added/kept/removed smoothly keeping in mind the ItemSets must exist while items are playing the equip/unequip animations so they cannot simply be removed on the exact frame they are no longer required. In some cases you may want to disable an ItemSet without actually removing it. This is when you would use the IsItemSetValid function.
ItemSets represent what items can be equipped at the same time in each slot. They are created by ItemSetRules.
In some cases you may want to use states to enable/disable them at runtime. This an easy way to prevent certain items to be equipped depending on the character state.
The state name that becomes active when the ItemSet is active. It can also be used to identify the ItemSet within an ItemSetGroup
An ItemSet can only be active if it is enabled.
Can Switch To
Can the ItemSet be switched to by the EquipNext/EquipPrevious abilities?
The ItemSet index that should be activated when the current ItemSet is active and disabled.