Cannot change GameObject hierarchy while activating or deactivating the parent.

Hello all, I am getting an error when I try I switch scenes or end the game with this code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StickyPlatform : MonoBehaviour
{

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.name == "Player" && collision.gameObject.transform.parent == null)
        {
            Debug.Log(collision.gameObject.transform.parent != null);
            collision.gameObject.transform.SetParent(transform);
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.name == "Player" &&  collision.gameObject.transform.parent != null)
        {
            collision.gameObject.transform.SetParent(null);
        }
    }
}

As you can see, I tried to check if the parent of the object was or wasn’t null before I changed it but this still results in the same error. Someone had posted a thread like this years back but hasn’t gotten any answers so I am now posting this to see if anyone can help me

Ok, so what is the error?

Sorry should have clarified the error
It is: cannot set the parent of the game object “Player” while activating or deactivating the parent game object “platform-long”. Platform long being the game object this script is attached to

I have a hunch that you are calling SetActive() in another collision callback, namely the platform the player is on. If so, you can either combine the reparenting and SetActive code so that the parent is set before SetActive is called. Alternatively you can start a coroutine that yields null and then reparent.

Btw, Collision2D has a transform property, so there’s no need to go through gameObject every time:

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.name == "Player" && collision.transform.parent == null)
        {
            Debug.Log(collision.transform.parent != null);
            collision.transform.parent = transform;
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.name == "Player" &&  collision.transform.parent != null)
        {
            collision.transform.parent = null;
        }
    }

And SetParent() is only really useful if you use the worldPositionStays parameter, otherwise just assign to .parent property.

I didn’t remember ever deactivating the platform and I checked my code and I haven’t used the setActive function on it, but the error comes when I close the scene or switch scenes. I didn’t think that gameobjects deactivate when you switch scenes. Additionally, I also Debug.Logged whether or not the platform was active and it was always active, even when I close the scene but for some reason when I end my game it says I cannot set the parent of “Player” while activating or deactivating “platform-long” (name of platform), which makes no sense because the platform is never deactivated. Should I report as a bug?

Having exactly the same problem.
I even tried moving where the parent is set from the player to the platform, but both approaches give me the same error.
To further clarify, it seems the error only occurs when ending the scene or play mode is stopped while the player is on a platform

1 Like

It’s a pesky error to be honest. It seems to occur in Unity 2022 upwards.

When a scene gets unloaded (play mode stopped, level restarted, moved to next level etc…) you would expect Unity to simply delete destroy everything on its own in the background and that you wouldn’t have to worry which game object will randomly get destroyed before the other and make a collision/trigger on exit callback. But it seem that now it makes a difference in the unparenting aspect.

Maybe people with more experience can chime in but I found no bulletproof solution, you just need to do some checks such as ActiveInHierarchy, change the order of things, make delays, etc… whatever works.