I found an interplay between the PickupSpawner, Portal logic, and the save system wherein after a save - items would respawn after a save, even if they have been picked up and placed in inventory, creating a flow of additional items after saves.
I believe the issue was the PickupSpawner checking for GameObject Null in the PickupSpawner class:
/// <summary>
/// True if the pickup was collected.
/// </summary>
public bool isCollected()
{
return GetPickup() == null;
}
Which in turn depends upon the null being set by:
private void DestroyPickup() {
if (GetPickup()) {
Destroy(GetPickup().gameObject);
}
}
The issue here is that Destroy marks an object for deletion, but does not delete until the end of the frame. So, if you check for null immediately after destroy, you could get a non-null result. And so, the save system will save the Pickup as not having been picked up.
Two solutions - one, is to add a bool to check for pickupIsDestroyed, rather than perform the null check:
public bool isCollected() {
bool check = pickupIsDestroyed || GetPickup() == null;
return check;
}
private void DestroyPickup() {
if (GetPickup()) {
Destroy(GetPickup().gameObject);
pickupIsDestroyed = true; ;
print("in Destroy - GetPickup is: " + GetPickup());
}
}
Another is to insert a yield return null in the Portal.cs Transition() Coroutine to force another frame before the last save - ensuring the null checks are processed correctly after Garbage collection.
Not sure if others are running into the same - i was wondering where all the extra goodies in my inventory were coming from!
Curious if anyone else ran into this and welcome feedback on the proposed solutions.
Cheers!