Manage Hierarchy Children Using Enum Dictionary in Unity
When developing a Unity project, there are many cases where you need to manage child objects under a GameObject's Hierarchy through code.
The simplest approach is to store the child objects using an array ([]) indexed by numbers (0, 1, 2, ...). However, this method has a major drawback: "Index numbers do not describe meaning." (You can't tell just by looking at a number what state it represents.)
Moreover, trying to use enum values by casting them to integers ((int)enum) also hurts code readability and maintainability.
Improving the Structure with Dictionary Instead of Arrays
By using a Dictionary, you can manage objects with the Enum as the key and a List of objects as the value.
- Access with meaningful names instead of numbers.
- Greatly improved code readability and maintainability.
Basic Structure
private Dictionary<PlayerState, List<Transform>> playerStateDic;
PlayerState is the enum representing the states you want to manage. Each state will be mapped to its corresponding list of child objects.
Initialization Process
First, initialize the Dictionary with empty lists for all enum values automatically.
playerStateDic = new Dictionary<PlayerState, List<Transform>>();
foreach (PlayerState state in Enum.GetValues(typeof(PlayerState)))
{
playerStateDic[state] = new List<Transform>();
}
This way, even if new states are added later, you won't need to manually adjust the code.
Linking Hierarchy Child Objects
Loop through each Transform child and match the name with the Enum name automatically. (In Unity's Hierarchy window, make sure that the child objects' names match the enum names.)
foreach (Transform child in transform)
{
if (Enum.TryParse<PlayerState>(child.name, true, out PlayerState state))
{
foreach (Transform subChild in child)
{
if (subChild != null)
{
playerStateDic[state].Add(subChild);
}
}
}
else
{
Debug.LogWarning($"{child.name} is not a valid PlayerState.");
}
}
Enum.TryParse is used to safely convert the string name into an Enum value. If conversion succeeds, the Hierarchy is automatically linked.
Practical Example
Here is an example of safely retrieving and using objects registered in the Dictionary.
private void UpdateMoveObjects(int activeIndex)
{
if (!playerStateDic.TryGetValue(PlayerState.Move, out List<Transform> moveList))
{
Debug.LogWarning("$"Move list not found. (Index: {activeIndex})");
return;
}
int count = 0;
foreach (var obj in moveList)
{
if (obj != null)
{
obj.gameObject.SetActive(count == activeIndex);
}
count++;
}
}
Using TryGetValue allows you to safely handle cases where the key might not exist. Only the required object is activated, and the others are deactivated.
Summary
- Eliminates index confusion that can occur when using arrays.
- Allows direct access to objects by enum names, making the code easier to read.
- Enables safe name-based matching through
Enum.TryParse. - Ensures safe Dictionary lookup using
TryGetValue.
