Add Moving Platforms

Obstacles are often useful in creating interesting game mechanics. A moving platform is an example of an ostacle, or at least a means to overcome an obstacle.

Horizontal Movement

Build a platform that moves side to side.



Add a third platform as a child of Platforms. Move and scale the platforms so one platform hovers between two large platforms. The gap between all platforms should be too wide for the player to jump across.



Right-click on the small platform and select Unpack Prefab Completely. This will convert the prefab back into a regular GameObject as indicated by the blue icon in the heirarchy changing to gray. You will use this GameObject to create a different prefab for moving platforms.



Rename this GameObject to MovingPlatform, create a script named MovingPlatformBehavior, and attach the script to the MovingPlatform.



Update the script to the following code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovingPlatformBehavior : MonoBehaviour
{
    public float minFromStart = -10f;   // 0 or negative
    public float maxFromStart = 10f;  // 0 or positive
    public float speed = 6f;    // negative for left, positive for right

    private float min, max;

    void Start()
    {
        min = transform.position.x + minFromStart;
        max = transform.position.x + maxFromStart;
    }

    void Update()
    {
        float x = transform.position.x;
        if (x > max || x < min) speed *= -1;

        transform.position += Vector3.right * speed * Time.deltaTime;
    }
}
              

This code will move the platform it is attached to horizontally between the min and max values at the specified speed. The min and max are private so cannot be set in the editor directly. Instead, they are initialized in the Start method using the values of the public properties minFromStart and maxFromStart.



Imagine the platform's position had an x value of 100. Setting the minFromStart property to -10 would cause the min property to be set to 90 (the sum of 100 and -10). Likewise, setting the maxFromStart property to 10 would cause the max property to be set to 110 (the sume of 100 and 10). The platform would move back and forth between 90 and 110, or 10 units to the left and ten units to the right from its initial starting position.

The speed is also a public property whose value represents the number of units per second the platform should move. If positive, the movement will be towards the right. If negative, the movement will be towards the left.

The Update method first reverses direction if the platform has moved too far in one direction. That is, if the x value of the platform becomes greater than the max or less than the min, the direction is reversed by multiplying by -1.

Lastly, the position of the platform is updated to a new position. Vector3.right is a Vector3 object with values of 1, 0, 0. Adding this vector to a position will move the object one unit to the right. The magnitude and direction of movement will be based on the speed. Finally, as discussed in the Bouncy Box lesson, muliplying by Time.deltaTime adjusts for the framerate.

Play the game to test the moving platform. Notice that after the player lands on a platform, it slides out from underneath the player.



Modify the code so the player moves with the platform.

public class MovingPlatformBehavior : MonoBehaviour
{
    public float minFromStart = -10f;   // 0 or negative
    public float maxFromStart = 10f;  // 0 or positive
    public float speed = 6f;    // negative for left, positive for right

    private float min, max;
    private GameObject player = null;

    void Start()
    {
        min = transform.position.x + minFromStart;
        max = transform.position.x + maxFromStart;
    }

    void Update()
    {
        float x = transform.position.x;
        if (x > max || x < min) speed *= -1;

        transform.position += Vector3.right * speed * Time.deltaTime;

        if (player != null)
        {
            player.transform.position += Vector3.right * speed * Time.deltaTime;
        }
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.tag == "Player")
        {
            player = other.gameObject;
        }
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject.tag == "Player")
        {
            player = null;
        }
    }
}
              

The player property stores a reference to the player when the player is on the moving platform. The value of player property will be null when the player is not on the platform.

At the end of the Update method, whenever the player is on the platform (the value of player is not null), the player is moved by the same amount as the platform.

Finally, after the Update method, add two additional methods are used to set the value of the player property when the player lands on or jumps from the moving platform.

The OnCollisionEnter function is a built in function that executes whenever the collider on the object the script is attached to (the MovingPlatform) collides with another collider (attached to the other object).

If a collision with the movingPlatfrom occurs, the built-in Unity OnCollisionEnter function automatically executes. The parameter passed provides a Collision object that may be used as a reference to the other object involved in the collision.

The code within the OnCollisionEnter function, sets the value of player if the object colliding with the MovingPlatform is tagged as a Player.

Similarly, the code within the OnCollisionExit function sets the value of player back to null if the objects that stops colliding with the MovingPlatform is tagged as a Player.

After saving the code, return to Unity and tag the ThirdPersonController as a Player.



Play the game to ensure the player is able to stand on a moving platform without it sliding out from underneath. Also check that the player is able to move as expected while on the platform. Finally, check what happens when you collide with the side or bottom of a moving platform.



Usually there are many ways to accomplish the same behavior. You will likely find many solutions by searching the Internet for how to create moving platforms in Unity. The following video provides a very quick method that utilizes animation and triggers.



Understanding the pros and cons of various methods will help you make the best decision for the game mechanics you intend to implement.

While the method used in the video is very elegant, the script created in this lesson will provide more flexibility in behavior.

Vertical Movement

Modify your script to support vertical movement.



To add for flexibility to the script, add horizontal as a public property of type bool with a default value of true. When this property is checked on, the platform should move horizontally. When checked off, the platform should move vertically.

public class MovingPlatformBehavior : MonoBehaviour
{
    public bool horizontal = true;
    public float minFromStart = -10f;   // 0 or negative
              

Next, modify the Start method to set the min and max using the x value of the platform's position when moving horizontally, or by using the y value of the platform's position when moving vertically.

void Start()
{
    if (horizontal)
    {
        min = transform.position.x + minFromStart;
        max = transform.position.x + maxFromStart;
    }
    else
    {
        // vertical
        min = transform.position.y + minFromStart;
        max = transform.position.y + maxFromStart;
    }
}
              

Lastly, modify the Update method by adding a block of code for vertical movement. This code is similar to the block used for horizontal movement but uses the y value of the position and the Vector3.up.

void Update()
{
    if (horizontal)
    {
        float x = transform.position.x;
        if (x > max || x < min) speed *= -1;

        transform.position += Vector3.right * speed * Time.deltaTime;
        if (player != null)
        {
            player.transform.position += Vector3.right * speed * Time.deltaTime;
        }
    }
    else
    {
        // vertical
        float y = transform.position.y;
        if (y > max || y < min) speed *= -1;

        transform.position += Vector3.up * speed * Time.deltaTime;
        if (player != null)
        {
            player.transform.position += Vector3.up * speed * Time.deltaTime;
        }
    }
}
              

Save the script and play the game with the horizontal property checked on. The game should play the same as before.

Stop the game and uncheck the horizontal property. Change the Min From Start to -5 and the Max From Start to 5 so that platform does not move as far. Reduce the Speed property of the platform to 2. When the game is played now, the character is able to ride on the platform as it moves up and down.



Notice the player appears to jump higher when the platform is moving downward and not as high when the platform is moving upward. This is expected behavior for two objects moving in the same or opposite directions.

If the speed of the platform is too high, strange behavior will occur as the platform moves downward. This is because the platform is falling faster than the player would naturally fall due to gravity.

Likewise, if the speed is too high, strange behavior will occur when the player jumps as the platform is moving upward. This is also expected behavior for a platform that is moving up faster than the player is jumping up.

Create a Prefab

Create a prefab of the MovingPlatform once it is complete so it may be used to quickly add more moving platforms.



Drag the MovingPlatform from the Hierarchy into the Assets > Prefabs folder. The icon in the Hierarchy next to the MovingPlatform turn should turn blue to indicate it is now a prefab.



Use the prefab to add another moving platform into the scene. In the Hierarchy, move the newly added MovingPlatform to be a child of Platforms.



Change the speed property to negative so it will begin moving in the opposite direction of the other moving platform. Then play the game to test it out.



Now you have a Platform prefab that allows you to quickly add stationary platforms and a MovingPlatform prefab that allows you to add platforms that move either horizontally or vertically.

Challenges

Build out a level a full level by attempting some of the following challenges.


  1. Using platforms and moving platforms, build out a complete level.
  2. Add fireballs (review lesson from Bouncy Ball game)
  3. Create a UI win panel that appears when a GameObject at the end of the level is reached.
  4. Create a UI element that displays a countdown clock. Update the clock every second and add code to end the game when the clock reaches zero.


  5. The platformer is one of the games you will be able to choose for your final project for the course. Additional lessons provided for the platformer include adding various types of enemies, among other features.