Are you seeing strange issues before this fix? I think I understand why you might think that the reference to playerEquipment was stale, but let me assure you that there shouldn’t be any stale references here. It might help to look at what data we are caching in EquipmentUI and what happens whenever we call equipmentUpdated
First, the caching… when the UI is first loaded, it gets a reference to the Equipment component on the player:
Equipment playerEquipment;
// LIFECYCLE METHODS
private void Awake()
{
var player = GameObject.FindGameObjectWithTag("Player");
playerEquipment = player.GetComponent<Equipment>();
playerEquipment.equipmentUpdated += RedrawUI;
}
This is just a reference to the component itself, which is physically attached to the player.
Then when we redraw the UI, we simply do this:
void RedrawUI()
{
icon.SetItem(playerEquipment.GetItemInSlot(equipLocation));
}
Once again, we’re relying solely on the reference to the Equipment component on Player that we cached in Awake. Our only source of information is whatever information the GetItemInSlot() returns. We don’t have access directly to the data inside Equipment, only what the Equipment component gives us.
Now in Equipment, we do have a dictionary which contains the slot data:
Dictionary<EquipLocation, EquipableItem> equippedItems = new Dictionary<EquipLocation, EquipableItem>();
And it is true that in RestoreState, we’re discarding that information in favor of the contents of the save file
void ISaveable.RestoreState(object state)
{
equippedItems = new Dictionary<EquipLocation, EquipableItem>();
var equippedItemsForSerialization = (Dictionary<EquipLocation, string>)state;
foreach (var pair in equippedItemsForSerialization)
{
var item = (EquipableItem)InventoryItem.GetFromID(pair.Value);
if (item != null)
{
equippedItems[pair.Key] = item;
}
}
}
But the reference to Equipment in EquipSlotUI remains unchanged. We’re not destroying and replacing the component reference itself, just the underlying data within the component.
If you were to put this check in RedrawUI()
if(playerEquipment!=Equipment.GetPlayerEquipment()) Debug.Log("This will never print");
you’d never see the debug message because the reference itself to the component will have been unchanged by RestoreState()
public EquipableItem GetItemInSlot(EquipLocation equipLocation)
{
if (!equippedItems.ContainsKey(equipLocation))
{
return null;
}
return equippedItems[equipLocation];
}
this method only returns the underlying data from equippedItems. Before RestoreState() it would return the data that was available before, after it would return the data in the newly created equippedItems.
This is one of the core principles behind encapsulation. Outside classes don’t have direct access to the data themselves, they have access to the data returned by the class. This allows us to do what we’re doing without having to recache references.
One further bit of evidence that playerEquipment is not changing… you’re still getting the RedrawUI, which is tied only to the event in playerEquipment… if playerEquipment itself were no longer valid, you woudln’t get the event.