Adding an Elevator to the 2.5D Platformer Prototype in Unity 2021
In this article we’ll allow the player to call an elevator if they have enough coins and ride it up to a different platform level.
I’ll be working with a GameDevHQ provided scene environment.
I’ve replaced the collectables, canvas, and player game objects with those from my last article.
I’ve also brought over my Cinemachine Virtual Camera setup and LevelManager game object.
The rest of the scene is composed of primitive game objects that you can recreate if needed.
I could have replaced the platform as well, but simply setting the Moving_Platform game object’s Rigidibody to “Is Kinematic” has it functioning, so why waste the effort.
Do note that I am in the same project but a different scene from previous articles and the settings covered in previous articles to make parenting the player to a game object move correctly are still in effect.
The coin functionality that I’ve imported from my previous article will be used here to determine if the player can call the elevator.
Let’s Get Started
If I hit play right now, we can see that most of the functionality is there, we just need to implement calling the elevator.
The scene comes with the Elevator_Panel game object already having a Box Collider which is set to “Is Trigger”.
The ElevatorPanel Class/Script
We’ll create a new script and assign it to the Elevator_Panel game object.
We’ll add a simple public method that returns the number of coins the player currently has to the PlayerInventory class/script.
In our new ElevatorPanel class/script we’ll need class variables to hold references to the elevator panel light and the actual elevator.
We’ll check that the player has at least coins on trigger enter.
Then we’ll use GetComponent<MeshRenderer>().material.color to change the color of the light on the elevator panel.
When the player enters the trigger, it will turn green.
When the player exits the trigger, it will turn red.
Now we can assign these transforms in the Unity Editor to our ElevatorPanel script component.
If we save and run our game, we can see the elevator panel light is behaving as desired.
Now we need to make the elevator actually move.
We’ll create an Elevator class/script to actually move the elevator around.
We’ll need some values for the speed of the elevator, if the elevator is at its top or bottom position, the locations of its top and bottom positions, and whether it is currently moving up or down.
Remember to assign the Elevator script to the Elevator game object.
For testing purposes, I’ve set the elevator to move down as soon as the game starts.
As shown above, the elevator is behaving as expected so I’ll remove this call from the Start() method.
Once again, we use FixedUpdate() in our script for the movement as this is well suited to physics interactions.
This may look more elaborate than it is for each move elevator sequence.
Essentially, I wanted the elevator to have a minor delay when called which necessitates a coroutine but I don’t want to make the coroutines public.
So the public MoveUp() MoveDown() methods call the MoveElevatorUp/Down() coroutines which then call the MovingUp()/MovingDown() methods.
This way I can directly call the MovingUp()/MovingDown() methods from FixedUpdate(), or these methods would only fire once.
We are also making use of Vector3.MoveTowards again.
I also want to add the OnTriggerEnter() method shown above to the Elevator class/script.
This will automatically set the elevator in motion once the player has walked on to it.
This follows the same process as we tested, so there will be a 2 second delay before it moves.
With our elevator code functioning, we need to return to the ElevatorPanel class/script and call it.
At this point I realized I’d rather directly assign the Elevator script component than thte ElevatorTransform reference so I modified the ElevatorPanel script as shown above.
I’ve also added the MoveDown() call for when the player calls the elevator.
A simple drag and drop and we are back in business.
If we hit play and test this out, we are partially successful.
The elevator panel calls the elevator down but the player entering the elevator does nothing.
The issue is simple.
I forgot to add a collider with Is Trigger!
Easy enough, we’ll add our box collider and adjust the Center settings to position where the player will be standing.
Looks good to me!
If we hit play and test it out, we can see it is working for the most part.
However, the elevator game object shakes when moving.
For one thing, we need to add a rigidbody to the Elevator game object.
I’ve also removed “Use Gravity” and constrained all rotations.
Spot The Difference
Since we have a working up/down mechanic with a moving platform (green in scene), we should be able to see why that works without jitter but our elevator does not.
I poured over the Rigidbody, Box Colliders, and related settings making sure they were identical.
Still no luck.
So, what gives?
The issue isn’t in the Unity Editor settings for these game objects.
It’s in the code.
More specifically, while the PlayerController script is coded to parent to the moving platform, it does nothing when interacting with the elevator!
Tag the Elevator
We’ll need to add a tag to the Elevator game object for this to work.
I’ve chosen to start all moving game object tags with “Moving” followed by their description for a reason.
I don’t need to check for each individual tag if I maintain this naming structure.
I can simply check if they start with “moving”.
The downside is that I no longer get the performance benefit of using CompareTag.
I think this is a good tradeoff for an infinite number of CompareTag calls for every moving game object!
If we run the game, we can see that the player game object parents to the moving platform and the elevator.
While it unparents due to jumping from the moving platform, it does not unparent from the elevator because the player did not jump.
Up until now, this has been my entire approach to unparenting the player game object from a moving platform.
We simply add the OnTriggerExit() method and reset the parent to null.
If we run the game, we can see that the parenting/unparenting behavior is working correctly.
However, I’ve discovered a new bug!
If the player jumps up and down while the elevator is moving, the elevator breaks!
OnTriggerEnter() Method in Elevator Class/Script
If we look at the Elevator class/script and the OnTriggerEnter() method, we can see that anytime the player enters the trigger collider we will call the elevator.
We should avoid executing this code if the player is currently in the elevator.
Our modified OnTriggerEnter() method checks the status of _movingUp and _movingDown before executing.
If we run our game, we can see that parenting is working correctly and that the elevator moves correctly even when the player jumps up and down on it.
ADDENDUM: When the elevator kept shaking in a later scene with more than primitive game objects, the solution was to add a Rigidbody to the Elevator game object without Use Gravity enabled, IsKinematic enabled, and Interpolate enabled.