Unity Create a Moving Platform the Player Character Can Stand On

unity moving platform

Unity Create a Moving Platform the Player Character Can Stand On

Moving Platforms In Unity

Moving platforms are a staple in any platformer. Platforms create a target for players to aim for when traversing the level. Landing on a platform is a test of the player’s hand eye coordination as well as their skill at controlling the player. Platforms that are moving provide an even greater challenge. Having a player move on a platform can also be a way to transition from scene to scene or even show progression as the player climbs higher in the level.

Implementing moving platforms in Unity can be a challenge. You have to not only account for collisions and moving the platform on a set path, but you also have to carry the player. If you have not implemented one before, you may be surprised it is not as easy as just having the player land on the platform. In this Unity tutorial, we are going to discuss how to create a platform movement script and two different ways of moving the player, with and without parenting. Settle in and let us carry you along for the ride.

Create a Platform to Move

Obviously, the first thing we are going to need is a platform. To create one, we have taken three pieces from a sprite sheet and nested them into one object. If you only have one sprite this will work the same way, just add the sprite that you want to use.

To determine when a player is on our platform we added a box collider to our object. This will allow us to check for collisions and then apply logic to our player’s position later on.

Next, we attached a Rigidbody2D. This will allow us to move our platform through physics. Later, it will give us the option to apply transfer physics properties to our player.

Set the Rigidbody2D to kinematic. We do not need to simulate gravity since we are moving the position through script. Also, platforms defy physical properties such as gravity and drag, sorry Sir Newton.

moving platform

Moving the Platform

Now, we have a platform that our player can stand on. Time to start writing the code to move it.

player on moving platform

Create a script called MovePlatform and attach it to the platform GameObject we created. Since we want the platform to move back and forth at a steady pace, the best way to move the platform is by lerping the position between two points.

The code provided below was created for another tutorial, but basically we will pass in the object we want to move and the target location. We will also use a speed variable to control how fast the platform moves back and forth. If you want to know more about how lerping works and the details of the script, check out the link above.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class MovePlatform : MonoBehaviour
{
 
    IEnumerator Vector3LerpCoroutine(GameObject obj, Vector3 target, float speed)
    {
        Vector3 startPosition = obj.transform.position;
        float time = 0f;
 
        while(obj.transform.position != target)
        {
            obj.transform.position = Vector3.Lerp(startPosition, target, (time/Vector3.Distance(startPosition, target))*speed);
            time += Time.deltaTime;
            yield return null;
        }   
    }
 
}

Moving Platform Back and Forth

So, we know how we are going to move the script but how do we use it for our moving platform? First we need to go back to our editor and create two positions in our scene. We do this by creating two empty GameObjects and moving them to the places we want our platform to start and end. We have named ours PlatformPathStart and PlatformPathEnd to make them easier to identify.

moving platform back and forth

Dive back into your script and create public fields where we can assign our start and end positions. While you are here, go ahead and create a public field that holds an int for our speed. Create two private fields for holding the Vector3 positions of our two path ends.

    public GameObject platformPathStart;
    public GameObject platformPathEnd;
    public int speed;
    private Vector3 startPosition;
    private Vector3 endPosition;

Inside of the Start method, assign the Vector3 values from the GameObject positions. Start is one of Unity’s life-cycle methods, check out our article on Start vs Awake vs OnEnable for more info. Second, we want to kick off the first movement of the platform by calling our lerp in a coroutine. This will be followed through in the Update method.

    void Start()
    {
        startPosition = platformPathStart.transform.position;
        endPosition = platformPathEnd.transform.position;
        StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
    }

Unity’s Update method is another lifecycle method that gets called each frame. Since we are using transform position for the movement here it is ok to use the Update method. Later on, when we use rigidbodies to move our platform we will use FixedUpdate. Check out our article on Update vs FixedUpdate in Unity to learn the difference between the two.

Inside the Update method, check if the current position of the platform is equal to the start or end positions. If it is we will use our lerp method to send it back the other way.

    void Update()
    {
        if(transform.position == endPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, startPosition, speed));
        }
        if(transform.position == startPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
        }
    }
unity moving platform

Having Unity’s Moving Platform Move the Player

At this point, we have a working platform. It floats in the air, moves back and forth, and the player can jump on it. But we have an issue. When the player lands on the platform, they do not move with it. This is because there is nothing holding the player to the platform or transferring velocity to the player.

moving platform player slides off

Platform Parenting to Move with the Player, the Easy Way

By far the easiest way to make the player move with the platform is to make the player a child of the platform. This works because child objects will inherit their positioning from the parent. Also, when the player moves on the platform, their position updates relative to the parent. The combination of the two makes using Unity’s SetParent method the quickest to implement.

We will use the colliders we added earlier to check for collisions by using OnCollisionEnter2D. Once an object collides with the platform, the platform will make itself the parent of that object. Pass in the true argument to tell Unity to keep our object where it is in world space when it landed.

    void OnCollisionEnter2D(Collision2D col)
    {
        col.gameObject.transform.SetParent(gameObject.transform,true);
    }

When the player leaves the platform we no longer need them to move with the platform. To do this we will use OnCollisionExit2D and parent of the object that left to null.

    void OnCollisionExit2D(Collision2D col)
    {
        col.gameObject.transform.parent = null;
    }

This implementation is super easy and means that any object that lands on the platform will move with the platform. This will work with items, enemies, or multiple players.

platform moving parent

Unity Moving Platform Without Parenting, the Hard Way

Now, there may be a reason you cannot parent your player to another object. If that is the case, we can still move the player, but we have to do so with rigidbodies. Also, since we will likely want to move other players, items, or enemies on the platform as well, we are going to need to do this on our character.

Create a PlatformMovement script and attach it to your player character. This will need a field for the player’s Rigidbody2D, the platform’s Rigidbody2D, and a boolean to trigger the movement.

public class PlatformerMovement : MonoBehaviour
{
    private Rigidbody2D rbody;
 
    private bool isOnPlatform;
 
    private Rigidbody2D platformRBody;
 
    private void Awake()
    {
        rbody = GetComponent<Rigidbody2D>();
    }
}

This time we need to detect if the player is touching the platform. To do so, we tagged our platform with the Platform tag. We check that the object we collided with has that tag and then set the boolean isOnPlatform to true and get a reference to the platform’s rigidbody. When the player leaves the platform, we set the boolean to false and the platform’s rigidbody to null.

    void OnCollisionEnter2D(Collision2D col)
    {
        if(col.gameObject.tag == "Platform")
        {
            platformRBody = col.gameObject.GetComponent<Rigidbody2D>();
            isOnPlatform = true;
        }
    }
 
    void OnCollisionExit2D(Collision2D col)
    {
        if(col.gameObject.tag == "Platform")
        {
            isOnPlatform = false;
            platformRBody = null;
        }
    }

As mentioned earlier, we now have to use FixedUpdate for updates since we are using physics properties. When the player is on the platform we will set the player’s velocity to match the platform’s. This will work both forwards and backwards. But you will notice the player may slide slightly when shifting directions.

    void FixedUpdate()
    {
        if(isOnPlatform)
        {
            rbody.velocity = rbody.velocity + platformRBody.velocity;
        }
    }

Add a physics material to the rigidbody of the platform to solve the sliding problem. Setting the friction to 7 worked for us but you may have to go higher depending on the player’s properties.

unity moving platform friction

Rigidbody Platform Movement Script

Lastly, we have to update the platform movement from lerping using the transform to lerping using the rigidbody. We also have to remove the collision detection, since we are doing that on the player level. These are small changes so I will lay out the full script here.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class MovePlatform : MonoBehaviour
{
    public GameObject platformPathStart;
    public GameObject platformPathEnd;
    public int speed;
    private Vector2 startPosition;
    private Vector2 endPosition;
    private Rigidbody2D rBody;
 
    void Start()
    {
        rBody = GetComponent<Rigidbody2D>();
        startPosition = platformPathStart.transform.position;
        endPosition = platformPathEnd.transform.position;
        StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
    }
 
    void Update()
    {
        if(rBody.position == endPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, startPosition, speed));
        }
        if(rBody.position == startPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
        }
    }
 
    IEnumerator Vector3LerpCoroutine(GameObject obj, Vector2 target, float speed)
    {
        Vector2 startPosition = obj.transform.position;
        float time = 0f;
 
        while(rBody.position != target)
        {
            rBody.MovePosition(Vector2.Lerp(startPosition, target, (time/Vector2.Distance(startPosition, target))*speed));
            time += Time.deltaTime;
            yield return null;
        }   
    }
}

Now, your player will move with the platform without parenting the object.

platform moving rigidbody

Character Platform Movement Script

Here is the full script for moving the player with the platform using rigidbodies. You can also attach this to anything that you want to move with platforms. All you need is a rigidbody and collider attached to the object with the script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
 
public class PlatformerMovement : MonoBehaviour
{
    private Rigidbody2D rbody;
    private bool isOnPlatform;
    private Rigidbody2D platformRBody;
    private void Awake()
    {
        rbody = GetComponent<Rigidbody2D>();
    }
 
    void FixedUpdate()
    {
        if(isOnPlatform)
        {
            rbody.velocity = rbody.velocity + platformRBody.velocity;
        }
    }
 
    void OnCollisionEnter2D(Collision2D col)
    {
        if(col.gameObject.tag == "Platform")
        {
            platformRBody = col.gameObject.GetComponent<Rigidbody2D>();
            isOnPlatform = true;
        }
    }
 
    void OnCollisionExit2D(Collision2D col)
    {
        if(col.gameObject.tag == "Platform")
        {
            isOnPlatform = false;
            platformRBody = null;
        }
    }
}

Platform Movement Script using Transform

This last script is the full platform movement script that uses parenting to move the player. If you were following along you may notice that it has been revised to use Vector2 instead of Vector3. Either way is appropriate, Vector3 will work for 2D and 3D objects while Vector2 will only work with 2D

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class MovePlatform : MonoBehaviour
{
    public GameObject platformPathStart;
    public GameObject platformPathEnd;
    public int speed;
    private Vector2 startPosition;
    private Vector2 endPosition;
    private Rigidbody2D rBody;
 
    void Start()
    {
        rBody = GetComponent<Rigidbody2D>();
        startPosition = platformPathStart.transform.position;
        endPosition = platformPathEnd.transform.position;
        StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
    }
 
    void Update()
    {
        if(rBody.position == endPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, startPosition, speed));
        }
        if(rBody.position == startPosition)
        {
            StartCoroutine(Vector3LerpCoroutine(gameObject, endPosition, speed));
        }
    }
 
    IEnumerator Vector3LerpCoroutine(GameObject obj, Vector2 target, float speed)
    {
        Vector2 startPosition = obj.transform.position;
        float time = 0f;
 
        while(rBody.position != target)
        {
            obj.transform.position = Vector2.Lerp(startPosition, target, (time/Vector2.Distance(startPosition, target))*speed);
            time += Time.deltaTime;
            yield return null;
        }   
    }
 
    void OnCollisionEnter2D(Collision2D col)
    {
        col.gameObject.transform.SetParent(gameObject.transform,true);
    }
 
    void OnCollisionExit2D(Collision2D col)
    {
        col.gameObject.transform.parent = null;
    }
 
}

And now you are ready to create your own moving platforms in Unity. Thank you for stopping by. Stick around and check out more of our tutorials or posts like our piece on Creating a Top Down Movement Script. Also, leave a comment telling us what you liked or did not like about the tutorial. Was it easy to follow along? What do you want to learn next? As always check out some of our published apps below.

2 thoughts on “Unity Create a Moving Platform the Player Character Can Stand On”

  1. Thanks for posting it. Moving player “the hard way” (without parenting) is not actually hard at all!

    One thing I wanted to point out is that you can replace coroutines of moving platform back and forth with a single line:

    obj.transform.position = Vector3.Lerp(startPosition, endPosition, Mathf.Abs(Time.time * timeScale % 2 – 1));

    You just need to calculate timeScale parameter based on distance between startPosition and endPosition and speed. Basically

    float timeScale = 1 / (Vector3.Distance(startPosition, endPosition) / speed);

    (could be simplified to just one division, I didn’t do it to make the formula more obvious).

  2. I’m getting no velocity from the platform. I wonder If they changed anything about kinematic rigidbodies.

Comments are closed.