Finishing up the 3D Platformer
- yasobel
- 7 oct. 2020
- 6 min de lecture
Dernière mise à jour : 25 oct. 2020
Bug fixing and adding some new elements.
I removed the FinishLine script and made a new one called Checkpoint that I will use to change the color of checkpoints on collision.

I modified the DeathWall script so that the player respawns at the checkpoint and not at the beginning of the game if he collided with it.
To do so, I start by checking if the checkpoint is active, meaning that the player collided with it. If it’s the case, the player’s position equals the checkpoint’s position.

To access the Boolean indicating if the checkpoint is active or not I used the GetComponent<Checkpoint> in the start() function.
Next, I added an animation to make some of the platforms move from left to right. But the problem that I’ve encountered is that the player doesn’t follow the platform’s movement when he’s on top of it.
So, to solve this problem I added the following script:

Whenever the player enters in collision with the platform, he becomes its child so that he follows the translation. And when the player is no longer on top of the platform, the parent is set back to null.
After testing the game, I noticed that I had to add a trigger box collider after the first box collider or the player won’t move with platform.

Then, I added some collectibles that the player has to collect in order to win the game. They’re represented by a yellow star and the number of ones collected is displayed in the top left part of the screen.
I inserted a TextMeshPro to display the score, an int named count and the 2 following functions:
When the player collides with one of the collectibles, we add one to count, we display the new number on the screen with the SetCountText() function and finally we remove the collectible.




Then I wanted to add some falling platforms as a trap, so that a few seconds after the player steps on the platform using the following script :

Tip:
I noticed that when using the cylinder help, the player kind of floats on top of the cylinder, so instead of using cylinders I used cubes and the problem was resolved.
But some problems remain unsolved:
-> I need to find a way to reset the score when the player dies depending on the checkpoints.
-> I need to add a condition so that the player only wins if he collects all of the stars.
-> The stars have to respawn whenever the player dies.
-> How to manage 2 checkpoints.
-> I tried to add a sound when the player collects the stars but it doesn’t seem to work.
-> When the player dies, the falling platforms don’t go back to their original positions, and surprisingly only one falling platform seems to work properly.
-> I'm having some trouble withe the moving platform, when stepping on the first one, the player doesn't move with it.
I eventually managed to solve some of them.
The Finish Line:
In order to display the WinText only when the player reaches the finish line and collects all of the stars I added the following condition in my EndZone script:

The script takes into account if "count" equals the total number of stars to display the text.
Managing 2 checkpoints:
When adding a second checkpoint I didn't know how manage both of them so that the position of the respawn changes when the player collides with any of them. I only tried to change the DeathWall script by adding variables and conditions but it didn't work so I decided to modify the Checkpoint script.
When the player collides with a checkpoint, the teleportTarget's position from the DeathWall script takes the coordinates of the checkpoint's position.
So, in DeathWall I only needed one respawn position which is initially set to the beginning of the platformer and that updates whenever the player collides with a checkpoint.


Collectible Sound:
I initially tried to add an AudioSource component directly to the collectibles that plays when the player collides with it.
So I had an AudioSource component in each collectible and the same AudioSource in my player's CharacterController. And I think that's the reason why it didn't work.
To make it work, I only added an AudioSource variable in my CharacterController script that is played once the player collides with a collectible and the problem was solved.


Moving Platforms:
I don’t know why the character doesn’t move with the first platform but moves with the second one although I did exactly the same thing for both. So I used the method that we saw in class that seems to work perfectly.
I started to remove the trigger collider, and added a rigidbody component. I froze the X and Y position as well as all of the rotations because the platform only moves on the Z axis.
Next, I changed the ObstacleMvmt script with the following :

What it does is add a constant force and velocity to the platform that we want to move.
In this case, the platform generates forces which makes the player also move with it.
So, when creating the animation, I don’t need to manually move the platform, I only have to change the Z value in the force component.
Falling platforms:
This is similar to what I've encountered with the moving platform. Out of the 3 falling platforms, only one works perfectly although they all have the same components. The only solution that I found was to duplicate the working platform and remove the others.
But, to make the platforms respawn after falling I had to re-do the script because the one that I used wasn't practical for this case. I wasn't able to manage the respawn position nor change it since it was constantly falling in the Update function.
So I did the following :


I started by adding a RigidBody to the platforms, then the trick was to enable or disable the isKinematic option and the Gravity for the platform to fall or not.
Enabling the isKinematic and disabling the Gravity keeps the platform in place. If it's the opposite, the platform falls down.
Then I added a DelayFallTimer function so that the platform starts falling 1 second after the collision (because otherwise it falls immediately and the player doesn't have time to jump) as well as a DelayRespawn function that automatically puts it back to its original position 5 seconds after the collision (The timer should be chosen so that the platform doesn't respawn when the player is on top of it, and so that in case the player dies it is back in place before he reaches it).
After solving the problems, I decided to add some traps that can kill the player :
1/ Ground trap:
I downloaded a trap prefab from the asset store and I added a simple script that teleports the player to the respawn position when colliding with it.


2/ Laser trap:
I wanted to add one last trap: a laser that turns off and on and that can kill the player when he touches it.
To do so, I added 2 totems to have an entry point and an exit point. Then I used a line renderer and a particle system to create the laser.

Next, I wanted to add a script that turns the laser on and off.
At first, I tried to loop two Invoke functions in my Update function. One of them turns off the laser and the other one turning it on. But, as much as I’ve tried to invoke both functions one after the other, it didn’t work.
After hours of looking for a solution, I stumbled upon the StartCoroutine and IEnumerator functions that helped me achieve the desired goal. I now have a laser that turns on and off every second.

Sadly, when trying the game I realised that the collider is still enabled even if the laser is turned off. I didn't find a way to disable it so that the player could walk through, so I decided to keep the laser on and that the player will have to jump to avoid being killed.
I eventually ended up with this simple script :

Adding a theme :
The next thing that I’ve done was trying to add a “Jungle” theme to my game.
I started by downloading a couple of packages to have access to trees, rocks, ground effects etc.
And I placed everything in my terrain object to create some sort of environment.
But, I don’t know if this is the best way to do it because I ended up with having a lot of objects in my hierarchy that I’ve placed in a folder. Maybe there’s a better and more efficient way of creating a theme.
Next I downloaded a Skybox to have a more realistic sky, and I obtained the following results:


Adding a timer :
And finally, the last step was to add a timer at the top right of the screen that stops when the player reaches the finish line. To do so, I added a UI Text named TimerText and the following script to the player as a component:

I used the Timer package to be able to implement the minutes and the seconds as well as displaying them.
Then I added a stopTimer function that I used in my EndZone script to stop the timer when the player wins.

I obtained the following result :

What I didn't manage to solve :
Score Reset:
I wanted to find a way to reset the score when the player dies depending on the checkpoints meaning that the stars have to respawn.
But I eventually changed my mind and decided that when the stars have been collected the player doesn't have to do it again.
Kommentare