Character flickering on moving platform

Hi everyone…
I created a lift for my 2D platformer, and when my player with rigidbody enter on it, I set the player as child of lift, and it works perfectly… The problem is when I walk on it!
The player stay slower, and flickering a bit, looking like the lift is holding him. I tried to make the lift as a rigidbody, and move it with velocity, solved this problem, but the player doesn’t stay stick to the lift. And if I use this lift horizontal, my player doesn’t move with this lift :confused:

- More Details:

My player character has Rigidbody and 2 Colliders2D, one Box for body and one Circle for legs, like the Standard Character Robotboy of Unity. For his movement I’m using:

playerRigidbody.velocity = new Vector2(move* maxSpeed, playerRigidbody.velocity.y);

My lift has a simple Box Collider2D and I’m moving it using:

using UnityEngine;
using System.Collections;

public class Lift : MonoBehaviour
{
    [SerializeField] private float speed = 20;
    [SerializeField] private Transform endPosTransform;
    [SerializeField] private GameObject player;

    private Transform myTransform;
    private Vector2 startPos;
    private Vector2 endPos;
    private Vector2 nextPos;

    void Start()
    {
        myTransform = transform;
        startPos = myTransform.localPosition;
        endPos = endPosTransform.localPosition;
        nextPos = endPos;
    }

    void Update()
    {
        SetMovement();
        SetDirection();
    }

    void SetMovement()
    {
        myTransform.localPosition = Vector2.MoveTowards(myTransform.localPosition, nextPos, speed * Time.deltaTime);
    }

    void SetDirection()
    {
        if (Vector2.Distance(myTransform.localPosition, nextPos) <= 0.1)
        {
            if (nextPos == endPos)
            {
                nextPos = startPos;
            }
            else
            {
                nextPos = endPos;
            }
        }
    }

    void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            other.transform.SetParent(transform);
        }
    }

    void OnCollisionExit2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            other.transform.SetParent(null);
        }
    }
}

**I uploaded a project with a character like my and the lift. If someone wants to check yourself what is happening when you walk on this lift: **
Download Project

If someone understand and could help me… Thank you!

Howdy, after doing some testing and discuss with our physics folks I have a solution for you. Basically, a game object with a rigidbody on it has a transform position and a body position. The body position drives the transform of the game object. In this instance, interpolating the platform is causing direct changes to the player’s transform, which is fighting with its rigidbody.

The easiest way to fix this is to stop parenting the player to the transform and instead simply move the player by the amount of movement of the platform every frame. Again, this movement needs to be calculated based off of the players body position and not its transform position (or else the same problem occurs). With all of that in mind, I modified your Lift script below. This is tested and works and avoids any hierarchy shuffling. You’ll notice I added a LateUpdate to move the player based on its body. Also, I no longer parent the player to the platform in the OnCollision method.

using UnityEngine;

public class Lift : MonoBehaviour
{
	[SerializeField] private float speed = 20f;
	[SerializeField] private Transform endPosTransform;

	private Vector2 startPos;
	private Vector2 endPos;
	private Vector2 nextPos;

	//ADDED
	private Rigidbody2D player;
	private Vector3 moveDelta;

	void Start()
	{
		startPos = transform.localPosition;
		endPos = endPosTransform.localPosition;
		nextPos = endPos;
	}

	void Update()
	{
		SetMovement();
		SetMoveDirection();
	}

	//Move the player by the change in movement of the platform using the player's rigidbody instead of parenting
	void LateUpdate()
	{
		if (player) 
		{
			Vector2 playerBody = player.position;
			player.transform.position = new Vector3 (playerBody.x, playerBody.y) + moveDelta;
		}
	}

	void SetMovement()
	{
		//Calculate desired position
		Vector2 desiredPosition = Vector2.MoveTowards(transform.localPosition, nextPos, speed * Time.deltaTime);

		//Use that position to figure out the change in position of the platform
		moveDelta = new Vector3 (desiredPosition.x, desiredPosition.y, 0f) - transform.position;

		//Apply the new position
		transform.localPosition = desiredPosition;
	}

	void SetMoveDirection()
	{
		if (Vector2.Distance(transform.localPosition, nextPos) <= 0.1)
		{
			if (nextPos == endPos)
			{
				nextPos = startPos;
			}
			else
			{
				nextPos = endPos;
			}
		}
	}

	void OnCollisionEnter2D(Collision2D other)
	{
		//Instead of parenting, grab a reference to the player's rigidbody
		if (other.gameObject.CompareTag("Player"))
			player = other.gameObject.GetComponent<Rigidbody2D>();
	}

	void OnCollisionExit2D(Collision2D other)
	{
		//Remove reference
		if (other.gameObject.CompareTag("Player"))
			player = null;
	}
}

Cheers

Parent the player to the platform when it makes contact with it

I know it’s an old issue but actually I had the same problem and answer might be helpful for someone else in the future.

So I assume you have 2 objects like Lift and Player. On collision you are adding Lift as a parent for Player object.

Create another object call it for example Platform and let it be a parent for Lift.
In script which is attached to Lift object try moving Platform instead of Lift, like this

 private void FixedUpdate()
 {
     transform.**parent**.position += (new Vector3(0,1f)* Time.deltaTime);
 }

It’ll move Parent of Lift which is Platform.

Instead of making Lift as a parent for Player you’ll need to make Platform as a parent for your Player

  void OnCollisionEnter2D(Collision2D other)
  {
      if (other.gameObject.CompareTag("Player"))
          other.transform.SetParent(transform.**parent**);
  }

In short words, use parent object to move your platform and his child object to detect collision. When collision is happening set Player’s parent to platform which is moving.

Have fun

EDIT:
It seems like flickering will appear when you change Scale of your Platform. So in your case you can scale Lift object but parent of Lift object which I proposed to add should not be scaled!