Having issues maintaining the relative position of one object to another moving object

Hi everyone, I have a problem regarding moving platforms and making the player follow along with them. I want the player (linkedRbs[i] in this case) to basically ‘stick’ to the object and maintain its relative position on the object as it moves - this works in a sense, the problem comes when setting the position of the RigidBody, the relative position gets inverted (diagram below for reference). If the player is relatively at the front of the object, the next physics update it will move the the back, then to the front, vice versa. I really can not find a way to fix this and keep it in the same relative position without the back forward motion - any help? It seems like a simple error that I’ve glossed over on my end but I’ve been trying to fix this for hours.

I move my rigidbodys with the moving platform as follows:

List<Rigidbody> linkedRbs = new List<Rigidbody>();
List<Vector3> linkedRbsRelativePos = new List<Vector3>();

private void FixedUpdate()
{
    for (int i = 0; i < linkedRbs.Count; i++) // "linkedRbs" are the rbs touching the moving object
    {
        if (GetRelativePos(linkedRbs[i]) != linkedRbsRelativePos[i]) // RB is not in the same place as it was the last physics update
        {
            Vector3 lastRBPos = linkedRbsRelativePos[i];
            linkedRbsRelativePos[i] = GetRelativePos(linkedRbs[i]);

            Vector3 worldRelativePos = transform.position - linkedRbsRelativePos[i];
            Vector3 newPos = lastRBPos + worldRelativePos;

            //Debug.Log($"Dir={worldRelativePos},lastPos={lastRBPos},newerPos={newer}");

            linkedRbs[i].MovePosition(new Vector3(newPos.x, linkedRbs[i].position.y, newPos.z));
        }
    }
}

private Vector3 GetRelativePos(Rigidbody rb)
{
    Vector3 playerRelative = rb.transform.InverseTransformPoint(transform.position);
    return playerRelative;
}

private void OnCollisionEnter(Collision collision)
{
    Collider collider = collision.collider;
    if(collider.TryGetComponent<PlayerColliderReference>(out PlayerColliderReference pcr))
    {
        Rigidbody _rb = pcr.GetComponentInParent<Rigidbody>();

        linkedRbs.Add(_rb);
        linkedRbsRelativePos.Add(GetRelativePos(_rb));
    }
}

private void OnCollisionExit(Collision collision)
{
    Collider collider = collision.collider;
    if (collider.TryGetComponent<PlayerColliderReference>(out PlayerColliderReference pcr))
    {
        Rigidbody _rb = pcr.GetComponentInParent<Rigidbody>();

        for (int i = 0; i < linkedRbs.Count; i++)
        {
            if (linkedRbs[i] == _rb)
            {
                linkedRbs.Remove(linkedRbs[i]);
                linkedRbsRelativePos.Remove(linkedRbsRelativePos[i]);
            }
        }
    }
}

If you’re moving your player around with AddForce then Unity’s physics will move your player’s rigidbody when it stands on the platform. You may need to constrain the platform’s Y axis to prevent it falling when the player stands on it. And you’ll also need to constrain/freeze the rotation axis of the platform. Or you could make the platform kinematic and move it with MovePosition.

Another option for moving a player with a platform is to use GetPointVelocity to get the velocity of the platform’s surface directly below the player and use it to pull/push the player along with the platform.

1 Like