Pickup stops working after destroying the object that created it

jmackenzie68

New member
Greetings,

I am creating a harvesting system and I have run into an issue where the Inventory Pickup prefabs stop working after harvesting(destroying) the plant. I have tested the inventory pickup in my scene in other instances and it works fine except for when using it with my custom script.

My script is called in the Interactable script's OnInteract() event. When the plant is fully grown I can interact with it and the Inventory pickup prefab drops and the plant is destroyed. The pickup is set to auto interact, but nothing happens, well... I can kick it around the ground, just not pick it up! When I press the interact key I get the following error:

MissingReferenceException: The object of type 'Interactable' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
Opsive.UltimateInventorySystem.Interactions.Interactable.Interact (Opsive.UltimateInventorySystem.Interactions.IInteractor interactor) (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/Interactable.cs:172)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.InteractWith (Opsive.UltimateInventorySystem.Interactions.IInteractable interactable) (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:156)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.Interact () (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:106)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.Update () (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:96)

My script:
Code:
    public void Harvest()
    {
        Debug.Log("Attempt to harvest" + gameObject.name);
        if (currentPlantAge >= growTime)
        {
            if (isMultiHavestable)
            {
                //set crop back one level
                //drop pickable crop

                //possibly check how many times its harvestable
                //check date/season for regrowth?
                GetComponent<ItemDropper>().Drop();

            }
            else
            {
                GetComponent<ItemDropper>().Drop();


                StartCoroutine(DestroySelf());
            }
        }
    }
    IEnumerator DestroySelf()
    {
        yield return new WaitForEndOfFrame();

        if (ObjectPool.IsPooledObject(gameObject))
        {
            ObjectPool.Destroy(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }


My Plant object:

The inventory pickup object that is create when interacting with my plant:
1632767197823.png


Please let me know if there is anything else I can provide to help solve this issue.

Thank you
Jared Mackenzie
 
Thank you for bringing this to my attention. I can't see anything wrong with your setup, so I thought perhaps something may be wrong in the interactor.

I made some changes which should prevent the error you are getting. Here is the new script, let me know if it works:
 

Attachments

  • InventoryInteractor.cs
    6.9 KB · Views: 1
Thank you for looking into this issue. I replaced my inventoryinteractor with that one and refreshed my project.

Unfortunately this made no change to the behavior. I still cant auto pick up the dropped inventory pickup and when pressing the action button i get the same error

MissingReferenceException: The object of type 'Interactable' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
Opsive.UltimateInventorySystem.Interactions.Interactable.Interact (Opsive.UltimateInventorySystem.Interactions.IInteractor interactor) (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/Interactable.cs:172)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.InteractWith (Opsive.UltimateInventorySystem.Interactions.IInteractable interactable) (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:163)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.Interact () (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:112)
Opsive.UltimateInventorySystem.Interactions.InventoryInteractor.Update () (at Assets/Opsive/UltimateInventorySystem/Scripts/Interactions/InventoryInteractor.cs:102)
 
That's very odd. So it would mean that the interactable object is destroyed midway through the Interact function.
For me line 172 is when the "EventHandler.ExecuteEvent" is called:
Code:
public virtual bool Interact(IInteractor interactor)
{
    if (!CanInteract(interactor)) { return false; }
    m_OnInteract.Invoke();
    EventHandler.ExecuteEvent<IInteractor>(gameObject, EventNames.c_Interactable_OnInteract_IInteractor, interactor);
    return true;
}

That would mean that the interactable component is destroyed during "OnInteract.Invoke()".

But that doesn't explain why you cannot pickup the item either before this error happens...

If you don't mind could you add some "Debug.Log(gameobject)" statements to know what object is is refering to, whether it is the plant or the item pickup?

perhaps a debug.log within the Disable or OnDestroy callback might help too:
Code:
private void OnDestroy()
{
    Debug.Log("Destroy "+gameObject);
}
private void OnDisable()
{
    Debug.Log("Disable "+gameObject);
}

Also double check the pickup inspector at runtime after it is spawned and before you try to pick it up. Make sure it is correctly setup and that you didn't mistakenly spawn the wrong prefab. Then see what happens to it in the inspector when you pick it up.
You can record a video about it if you think it migh help us get an idea of what can be wrong.

If none ofthat give us a better clue at what is wrong, you can send us your project at support@opsive.com and we can have a deeper look.
 
I've played with the code a bit and found a solution. Though I'm not sure if this will effect anything later on. I added a line to the Interact() function
after making this change everything seems to work as expected.


Code:
        public virtual bool Interact(IInteractor interactor)
        {
            if (!CanInteract(interactor)) { return false; }
            Debug.Log("Interacting with =  " + gameObject);

            m_OnInteract.Invoke();
            EventHandler.ExecuteEvent<IInteractor>(gameObject, EventNames.c_Interactable_OnInteract_IInteractor, interactor);
            interactor.RemoveInteractable(this);
            return true;
        }
 
Thank you for looking into this in more detail.
You solution will prevent being able to interact twice with the same object in a row.
But it gave me an idea. Now I cache the last interactor that interacted with that object. So on Disable I can remove it from the list if it isn't removed by default.

I also made a change to the Inventory Interactor such that it removes interactables that are disabled. That required a small change to the IInteractable interface.
These are the changes I'll have in the next update coming out very soon. So do let me know if you find any issues with them.
 

Attachments

  • Interactable.cs
    7.3 KB · Views: 1
  • InventoryInteractor.cs
    7 KB · Views: 1
  • IInteractable.cs
    1.4 KB · Views: 1
Top