2D physics bug - Descending platform throws character up into the air

I’m trying to make a game where the player can drag a platform down that a character is stood on. If they drag slowly, the character moves with the platform, however if they drag quickly then the platform moves down and the character will fall on their own under gravity.

I’ve almost got it working the way that I want, but sometimes when I pull the platform down quickly the character will get thrown upwards into the air (Seen at 8 seconds on the youtube video). There’s another case when sometimes the character will get stuck/attached to the platform floating above the platform (seen at 27 seconds on the youtube video). I’ve zipped the whole project up and linked to it. Any help that anyone can give me would be greatly appreciated!

Project zip here:
https://drive.google.com/file/d/0B8_B9WY-uqSmelcxdzVsbl8wN1U/view?usp=sharing

Video of the bugs here:

The bug where the character is thrown upwards happens quite a lot, the second bug (where the character attaches above the platform) happens towards the end of the video.

Just a heads up, most people on here will not be interested in downloading your whole project to help you. It would be best if you use code tags and paste the relevant classes into your post directly.

Yeah, I thought that might be the case; I was trying to avoid people asking about what settings I had on the rigid bodies, or how I’d set the project up by uploading an archive.

I’ll post the 2 bits of source code!

Character code:

Transform myParent = null;
    Transform myOriginalParent = null;
    public float myTolerance = 0.5f;

    Vector3 myParentPreviousPosition;

    void Start ()
    {
        myOriginalParent = transform.parent;
    }

    void LateUpdate()
    {
        if (myParent != null)
        {
            float delta = myParent.position.y - myParentPreviousPosition.y;
            Debug.Log(delta);
            myParentPreviousPosition = myParent.position;

            if (delta < -myTolerance)
            {
                Detach();
            }
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (myParent == null)
        {
            Collider2D collider = collision.collider;
            Attach(collider.transform);
        }
    }

    void Attach(Transform newParent)
    {
        myParent = newParent;
        transform.parent = myParent;

        Rigidbody2D rigidbody = GetComponent<Rigidbody2D>();
        rigidbody.isKinematic = true;
        rigidbody.simulated = false;

        myParentPreviousPosition = myParent.position;
    }

    void Detach()
    {
        myParent = null;
        transform.parent = myOriginalParent;
       
        Rigidbody2D rigidbody = GetComponent<Rigidbody2D>();
        rigidbody.isKinematic = false;
        rigidbody.simulated = true;
        rigidbody.MovePosition(transform.position);
    }

Platform code:

    public Camera camera;

    void FixedUpdate()
    {
        Vector3 mousePosInWorldSpace = camera.ScreenToWorldPoint(Input.mousePosition);
        Vector2 newPos = new Vector2(transform.position.x, mousePosInWorldSpace.y);
        GetComponent<Rigidbody2D>().MovePosition(newPos);
    }

You could do something like this and set the gravity scale to your liking

public class Movement : MonoBehaviour {

    public float myTolerance = 5.0f;

    private bool attached;
    private GameObject otherObject;
    private Vector2 otherObjectPrevious;


    void Start ()
    {
        attached = false;
        otherObjectPrevious = Vector2.zero;
    }

    void Update()
    {
        if (attached && otherObject != null)
        {
            transform.position = new Vector2(transform.position.x, otherObject.transform.position.y);
            float delta = transform.position.y - otherObjectPrevious.y;
            Debug.Log(delta);
            otherObjectPrevious = new Vector2 (otherObject.transform.position.x, otherObject.transform.position.y);

            if (-delta < myTolerance)
            {
                attached = false;
            }
           
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (!attached)
        {
            attached = true;
            otherObject = collision.gameObject;
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        attached = false;
        otherObject = null;
    }

}

So would I use the attached variable to drive whether the character was being affected by gravity? At the moment I’m having the rigidbody simulate the gravity and I just attach/detach the character from the platform he’s landed on.

instead of making the character a child of the platform you’re just moving it up and down with the platform instead of letting it move based on physics so long as it’s “attached”

The hovering issue from your video is likely due to the character and platform colliding at high speeds, and then the character getting parented at a weird offset. I would advise using the Rigidbody setting “Collision Detection: Continuous” to get more accurate collision results at high speeds. Try that and see if it helps with your other issues related to physics.

Did you check the physics material of your player? Maybe it is bouncy and jump up when fall from a height.

adding rigidbody.velocity = Vector2.zero; to your detach function might have the effect you want.