unity – Sticking the Rigidbody2D player to a moving platform without parenting & transform fiddling

I have a player entity with Rigidbody2D component and I have a moving platform which is a kinematic Rigidbody2D. Player movement is done by setting it’s velocity (body.velocity = newVelocity) and platform is moved via body.MovePosition.

I’ve made it so that the platform has a sensor which, when triggered, catches the Rigidbody2D of the entity that is on (currently only does that for player) and then I tried the following:

  1. Moving the player along the platform with caughtRigidbody.MovePosition. This keeps the player on the platform but the player is unable to move. It seems that MovePosition overrides any velocity change on the player and keeps him on the platform indefinitely. This would be ideal if I could have this behavior but keeping player movement.

  2. Moving the caught rigidbody by adding platform velocity to the body but it seems jittery and also happens to behave strangely when platform direction changes.

I got the player movement how I want it so I’m not willing to tear out the whole movement code and change the player to kinematic or something like that.

This is the relevant platform code:

public class MovingPlatform
{
    private void FixedUpdate()
    {
        // Only one node (initial position). Nowhere to move to
        if (worldNodes.Length == 1)
        {
            return;
        }

        // Target position reached?
        if (body.position == worldNodes(index))
        {
            // Is last (or first in backwards direction) target?
            if (direction == Direction.Forwards && index == worldNodes.Length - 1 ||
                direction == Direction.Backwards && index == 0)
            {
                // Change direction (forwards = 1, backwards = -1)
                direction = (Direction) ((int) direction * -1);
            }

            // set next target index
            index += (int) direction;
        }

        // Get target
        Vector2 target = worldNodes(index);
        // Get current platform position
        Vector2 position = body.position;
        // Calculate single-frame movement towards target
        Vector2 movementThisFrame = Vector2.MoveTowards(position, target, settings.Speed * Time.deltaTime);
        // Move platform by calculated movement
        body.MovePosition(movementThisFrame);
        // Calculate platform movement velocity (displacement / time delta)
        velocity = (movementThisFrame - position) / Time.deltaTime;
        MoveCaughtRigidbodies();
    }

    private void MoveCaughtRigidbodies()
    {
        foreach (Rigidbody2D caughtRigidbody in caughtRigidbodies)
        {
            // This keeps the player on the platform without jittering, but the player cant move
            //caughtRigidbody.MovePosition(caughtRigidbody.position + body.position - lastPosition);

            // This is spotty. It launches the player off the platform sometime when the platform changes direction
            // if (caughtRigidbody.velocity != velocity)
            // {
            //     caughtRigidbody.velocity += velocity;   
            // }
        }

        lastPosition = body.position;
    }
}