Position of object changes if parent is set to null?

I have been trying to make a moving platform and was able to get my player to parent to the object and it works fine. But when I try to step off the platform I set my player’s parent=null but then his global coordinates are set to the previous local coordinates from when he was on the platform causing him to move to a seemingly arbitrary location.

I have tried both restoring the global coordinates:

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

public class platformStay : MonoBehaviour {

    void OnCollisionEnter(Collision col) {
        col.transform.parent = transform;
    }
   
    void OnCollisionExit(Collision col){
        Vector3 temp = col.transform.position; // world pos
        col.transform.parent = null;
        //col.transform.position = temp; //This has no effect either
        col.transform.localPosition = temp; // restore world position
    }   
}

And I have also passed true to the “keep global position” parameter in SetParent:

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

public class platformStay : MonoBehaviour {

    void OnCollisionEnter(Collision col) {
        col.transform.parent = transform;
    }
   
    void OnCollisionExit(Collision col){
        col.transform.SetParent(null, true);
    }   
}

Neither of these seem to restore the global position and I was wondering if I was doing something wrong?

Thanks.

1 Like

I think I may have gotten a little closer by dynamically creating empty gameobjects and moving them into position before parenting my object to it. This was the only thing I managed to get working as setting the parent=null just wasn’t working…

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

public class platformStay : MonoBehaviour {

    void OnCollisionEnter(Collision col) {
        Transform oldEmpty = col.transform.parent;//first get the old empty (null if havnt touched platform yet)
        col.transform.parent = transform;//parent the object to the platform
        if (oldEmpty != null) {
            Destroy (oldEmpty.gameObject); //destry the old empty if it was ever created
        }

    }

    void OnCollisionExit(Collision col) {
        var newEmpty = new GameObject(); //the new empty to parent the object to
        Vector3 newEmptyPos = col.transform.position; //the position (x, z) for the new empty
        newEmptyPos.y = transform.position.y; //the position (y) for the new empty
        newEmpty.transform.position = newEmptyPos; //move the new empty
        col.transform.parent = newEmpty.transform; //set the new empty as parent of the object
    }

}

This still remains non-optimal as it doesnt handle scaling and just doesn’t work very well in general…

I absolutely can not seem to find a way to get Unity to stop changing the position of my player when the parent changes. I mean I can manually drag and parent things in the hierarchy during runtime and it works fine, but attempting the same thing programmatically keeps producing unexpected results. This is nuts!

Has this been resolve? I’m having the same issue trying to get off of a moving platform. I have no idea how to fix it.

When you set your parent transform, you can specify a second parameter of worldPositionStays. Set that to true.

someTransform.setParent(parentTransform, true);

Hi Thanks for the answer. So if I got this straight, the code would be something like this?

void OnCollisionExit2D(Collision2D other)

if (other.transform.tag == "MovingPlatform")
    {
           transform.parent = null;
           other.setParent(parentTransform, true);
     }

?

Thanks

SetParent (Yes, with a capital S) is part of the Transform class. You would need to use:

other.transfom.SetParent(parentTransform, true);

Note that looking at the documentation can save a lot of time waiting for people to reply.
https://docs.unity3d.com/ScriptReference/Transform.SetParent.html

2 Likes

Excellent! Thank you! I’ll give that a shot this evening.
Thanks again
Chris

Sorry but that did not work at all.

void OnCollisionExit2D(Collision2D other)
    {
        if (other.transform.tag == "MovingPlatform")
        {
            other.transform.SetParent(transform, false);
            transform.parent = null;
          
        }
    }

I also tried

void OnCollisionExit2D(Collision2D other)
    {
        if (other.transform.tag == "MovingPlatform")
        {
              transform.parent = null;           
              other.transform.SetParent(parentTransform, true);
          
          
        }
    }

This is the code used when getting off the moving platform. I looked at the documentation as suggested:

but it does not resolve the issue. Also, I get an error saying: The name parentTransform does not exist in the current context. If anyone else can give me some advice on this, it would be greatly appreciated. My project is stuck at the moment. Am I missing something? Is the syntax ok?

1 Like

Hi, I know this thread is old, but I have found the solution to your problem. I currently have Unity 2019.1.12f1, and I have created a mobile platform with this script:

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

public class MobilePlatform : MonoBehaviour {

    public Transform target;
    public float speed;

    private Vector3 start, end;

    // Use this for initialization
    void Start () {
        if(target != null) {
            target.parent = null;
            start = transform.position;
            end = target.position;
        }
    }
  
    // Update is called once per frame
    void Update () {
      
    }

    void FixedUpdate(){
        if (target != null) {
            float fixedSpeed = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards(transform.position, target.position, fixedSpeed);
        }
        if (transform.position == target.position){
            target.position = (target.position == start) ? end : start;
        }
    }
}

I hope it works for you!