3D Platformer GameDev Series – Weekly Blog #7: Adding Checkpoints

Hey everyone, I am now past a quarter of my way into the 3D platformer course! This past week, I learned how to add and set up checkpoints (which makes sense after setting up and completing the player respawn last week).

In 3D (and especially 2D) platformers, players often encounter locations or spots called checkpoints. Upon entering/visiting a checkpoint, the player will respawn there the next time rather than at the beginning of the level or stage.

Similar to how a killzone was created earlier for the player being ‘out-of-bounds’, an empty game object for the checkpoint is added to the scene and an appropriate collider attached to it with the “On Trigger” enabled (to allow the “Checkpoint” script to work; see further below). The game asset for the checkpoint (resembling a circular button/switch) is added and made a child of the empty checkpoint object and is then further duplicated; one of these assets represents the checkpoint’s ON state (which would appear yellow) and the other/duplicate represents the OFF state (which would appear greyish-blue):

AddingCheckpointToGameScene

The “Checkpoint” script attached to the checkpoint object introduces two new coding concepts. The first concept is the ability to pass a variable into a function being called in another script (the “GameManager” script in this case; see further down below). The second concept is the use of a “for loopto generate a list/array and to assign a number/element to each of the items in that list (in this case, all the checkpoint objects in the scene).

CheckpointScript

To see how the first concept works, the following is set up in the “GameManager” script:

GameManagerScript(checkpointNewSpawnPoint)

To see how the second concept would work, multiple checkpoints are added to the scene (which had already been done) and the final result looks like this when the game is run:

CheckpointsPlayerRespawn

You may have noticed when the checkpoint is active, there are some particle effects happening. This was also introduced in the course this past week using Unity’s built-in particle system. I must say, it had piqued my curiosity quite a bit! No doubt, I think it’ll be a lot of fun to play around in it sometime to create some very interesting effects. 🙂

But for now, stay tuned for next week when we will look at how to create a health system!

– Taklon

3D Platformer GameDev Series – Weekly Blog #6: Completing the Player Respawn

Hey everyone! It was a rather busy work week for me so today’s blog post will be relatively shorter than my previous posts for this series. Still, I did get a chance to go through and reproduce all the material covered so far in the 3D Platformer course on my own (as I said I would do each week before moving onto the next section of the course). Today, I will introduce Unity’s UI tools to finish setting up the player respawn by adding a fade in and fade out transition. Let’s hop right to it!

As you may know (whether consciously or not), User Interface (UI) is essential to all software applications and programs. In video games, the UI is comprised of all the screen displays that the user can see and/or access (i.e.- maps, inventory system, dialogue boxes, menus, etc..). The UI is also involved in generating screen transitions and effects.

In order to create a fade in and fade out transition for the player respawn, the first step is to create and add a UI object called a Canvas to the game scene. The canvas is set to scale with the screen size such that it can fit across any monitor’s resolution. The next step is to add a UI image (“BlackScreen”) under the canvas object. The UI image is resized to match the size of the canvas and to overlay it completely. Of course, an appropriate black colour is also assigned to it (the colour it will transition to and from):

Canvas (UI object)

After setting up the game scene, a new C# script called “UIManager” is attached to the canvas. In order to access Unity’s UI scripting elements and classes, the “UnityEngine.UI” namespace must be declared at the start of the script. This allows us to add and display a 2D Image or sprite to the canvas (a black screen in this case). Lastly, two boolean variables are used to generate the transitions (note: the coding is inversely written for the ‘fadeFromBlack’ transition which is not shown below but included in the script):

UIManager script (fadetoblack)

In order to call the transitions to occur, this is done in the GameManager script. Last week, we had set up the player respawn in the GameManager script by making the player disappear when it enters a killzone and then reappearing at the player’s starting position after 2 seconds. Now, we will trigger the two transition effects when the player disappears and when the player reappears (note: the camera is also disabled and re-enabled in order to fix an issue whereby the Cinemachine camera swivels around trying to follow the player which had just respawned at a distance from the killzone):

GameManager script (camerafix+fadetransition respawn)

By setting and enabling the fade from black transition as the default game state, the game begins with a fade transition – the final result of the complete player respawn looks like this when the game starts:

PlayerRespawnComplete

I must say, I am quite satisfied with my progress and pacing so far – and I think committing to a weekly blog is especially helping me stay on track. I’m already looking forward to this coming week, when I will learn how to create and add checkpoints/savepoints to the game. Stay tuned!

– Taklon

3D Platformer GameDev Series – Weekly Blog #5: Creating a Killzone and Setting Up Player Respawn

Wowzas! It seems like the past few weeks have just been rolling by! Alas, after spending a little over a month on learning how to setup the player and controls, I can now shift my focus to the game environment and its effect on the player. This week, I will demonstrate how to create a “killzone” – and with it, the player respawn.

So first of all, what is a “killzone“? Well, actually, this term is something that the course instructor, James Doyle, uses to define an area which kills the player upon entering it. In most 3D platformers, the main killzone is the one which defines the area that is ‘out of bounds’ – the player is usually killed if they fall or manage to jump into it. Below (click image to enlarge), you can see how such a killzone is created, re-sized, and positioned in the Unity game scene:

KillzoneObjectInGameScene

In the image above, you may have noticed that we also created and attached a new C# script (called ‘KillPlayer’) onto the ‘KillZone’ empty object. Also, enabling ‘Is Trigger‘ on the box collider added component allows us to then use a function in the script called “OnTriggerEnter“. In this case, the function will be used to respawn the player (Note: The player respawn function is being called from the GameManager script):

KillPlayerScript

So you might be asking, “Why is the Respawn function being called from the GameManager script and not coded and executed locally in the KillPlayer script?” “Individual scripts should only handle their individual elements“, James Doyle answers in response. For this reason, the Respawn function is set up in the GameManager script since the GameManager script controls things at a broader/global level. Not only does it make the code/logic easier to perform and follow, this also makes sense since player respawn can be triggered by more than just the player entering a killzone (e.g.- player being killed by an enemy, etc..). Here, we begin setting up the player respawn function in the GameManager script:

SettingUpRespawn

One thing to note above is that the newly introduced ‘Awakefunction is called before the ‘Start’ function. To keep the code more logical to follow and process, the ‘Awake’ function is used here to setup the GameManager ‘instance‘ before any code in the ‘Start’ function is executed. This is done in order for the KillPlayer script to call the Respawn function. The same is done in the PlayerController script; that is, an awake function is used to setup the PlayerController as an instance of itself when the game starts. However, to actually make the player respawn using these instances, we also require a new function called a Coroutine. A coroutine can be used to execute code to perform a series of events, and more importantly, allows the ability to pause the execution of that code in between while other code is executed (i.e.- in the update functions):

RespawningWithCoroutine

It can be a bit difficult to explain and understand the code (and I won’t go any further than what’s described above), but essentially, using a coroutine this way can allow us to achieve the following player respawn effect in the game:

BasicPlayerRespawn

Next week, we will finish setting up the player respawn by fixing the camera and jumping animation glitch upon respawning (as you may or may not have noticed) as well as including a fade out transition during the respawning.

I hope you enjoyed reading this week’s blog post. Stay tuned for next week’s!

– Taklon

3D Platformer GameDev Series – Weekly Blog #4: Jump Animation, Fixing Game Logic, and Improving Aesthetics/Controls

Hello everyone! I am now officially one month into the 3D Platformer Udemy course! Today, I will use what I learned last week in implementing idling and running animation states in order to add a jumping animation to our robot player. Along the way, I will fix some of the ‘game logic‘ concerning the player’s jumping ability and speed. Finally, I will setup and improve some of the general game aesthetics and controls. Alrighty, let’s dive right into Unity!

We begin by opening our Player Animator again and adding a new state for “Jumping”. We then assign our built-in robot jumping animation to it, disable exit time, and set an appropriate fixed duration for the animation (similar to what was done for the idling and running states last week):

AssignJumpAnimation(Animator)

Next, we create and assign a boolean parameter called “Grounded” (similar to the way we created the “Speed” float parameter before). To transition from our “Idle” to “Jumping” state, we can trigger this by setting a condition whereby the “Grounded” parameter is false (Note: the same condition applies for our “Running” to “Jumping” transition – which is not depicted below):

State Transition (idle to jumping)

The opposite transition (from “Jumping” to “Idle”) is triggered when “Grounded” is true and the “Speed” is less than 0.1 (Note: the same condition for grounded is true for our “Jumping” to “Running” transition except speed must also be greater than 0.1 – not depicted below):

State Transition (jumping to idle)

In our player controller script, we add a line of code at the bottom that would determine the value of “Grounded” (similar to how we had set and determined the value of “Speed” in the line of code just above it). At this point, we shall also fix a game logic issue whereby the player can jump higher and higher without ever touching the ground. This can be done by using a Unity function called “isGrounded” on our character controller (not to be confused with the “Grounded “parameter in our animator as it is not the same thing!) – which checks to see if the player is on the ground before the jump button can be pressed again:

JumpAnimationScript

A second game logic issue occurs when the player holds down two adjacent directional keys to move diagonally, causing the player to move almost twice as fast! In order to fix this issue, we add a line of code before the movement speed is determined to normalize the player movement speed regardless of the directional input.

Another game logic issue persists when the player walks off the edge of a platform. In this case, the player snaps instantly to the ground below the platform as a result of the speed of the gravity on the player continuing to increase indefinitely (until the jump button is pressed). This can be fixed by resetting the gravity speed to zero whenever the player is on the ground:

NormalizingMovementAndFallingOffEdgeFix

And onto the game aesthetics now! The first thing we can do is to hide the mouse cursor in the game. To do this, we add the following two lines of code in a new Game Manager script:

GameManagerScript (hide mouse)

Finally, we re-assign and add additional controls to enable full game controller compatibility. Of course, a must for any 3D platformer is to be able to rotate the camera – often achieved on the right analog stick:

SetupControllerInputs

Alas, our robot player is complete with most if not all of its game logic issues resolved! And… we can now use an X-box controller to test out the controls!

PlayerControllerAndAnimatorFinal

Next week, I will learn how to create a “killzone” (an area which would “kill” our player upon entering it). This would set the stage for us to implement a respawn system for our robot player. Thanks for reading and stay tuned!

– Taklon

3D Platformer GameDev Series – Weekly Blog #3: Player Rotation, Idling, and Running

Hello everyone! I’m almost a month into the 3D Platformer Udemy course now! This week, I will be covering Player Rotation, Idling, and Running. Let’s dive into Unity right away!

We’ll first start off with the relevant C# script (this is the same “PlayerController” script attached on our player object that we started working on last week):

BasicPlayerMove (rotating the player smoothly)

Now, I mentioned last week that I would not go into dissecting C# scripts. However, there is one class of functions in Unity of relevance to 3D game development that I feel would be remiss if I didn’t highlight here. This key class of functions is called the ‘Quaternion‘. The Qua-what now?! To simply put, a quaternion is used to represent rotations. It forms methods such as Quaternion.Euler, Quaternion.LookRotation, and Quaternion.Slerp. These methods (all used in the script above) allow us to do the following three things, respectively: to move our player in the appropriate direction according to the rotation of the camera, to rotate our player, and to do so in a smooth manner. With the use of quaternions in our script, the following result is produced:

playersmoothrotation

Next, let’s breathe some life into our robot! We’ll implement some animations to make our robot appear to look around (while standing still) and run as well. First, we create an Animator Controller and attach that to our player object. In the animator window (see below), we create two different states for the robot: ‘Idle’ and ‘Run’. We also create two transitions between the two states (as represented by the white arrows) as well as a parameter called ‘Speed’ to manage the conditions for these transitions to trigger later on:

PlayerAnimator (idle+run)

By clicking a state, an animation can be assigned to that state. The player robot model has built-in animations that can be used. For example, the “Robot_Idle” animation is assigned to the ‘Idle’ state as shown below:

AssignAnimation

It is important to note that for the transition from the ‘Idle’ to the ‘Run’ state, it should not have an exit time (meaning the transition can occur before the animation of the idle state is complete). Also, the transition should have a fixed duration (meaning it takes a specified amount of time to go from the ‘Idle’ to the ‘Run’ state):

StateTransition (idle to run)

The opposite also holds true (exit time should be disabled and there should be a fixed duration) for our player to go from its ‘Run’ state to its ‘Idle’ state:

StateTransition (run to idle)

In the last two screenshots above (on the bottom right), you may notice that we’ve assigned the “Speed” parameter we created earlier to the transitions. This allows us to set conditions that would trigger those transitions. If the speed for the ‘Idle’ state is 0 (zero), then for the ‘Idle’ to ‘Run’ transition, we want to set a condition that this transition would occur only if the ‘Speed’ parameter is – say – greater than 0.1. And for the ‘Run’ to ‘Idle’ transition, the condition for ‘Speed’ should then be less than 0.1.

Finally, in our player controller script, we create an Animator class to allow us to assign the animator controller we created to our player object. In our script, we also determine the value of the ‘Speed’ of the player based on whether the player is pressing/holding down any of the movement directional keys:

Script (idle or running animation)

Essentially, if the movement keys are being pressed, then the ‘Speed’ would be greater than 0.1 causing the ‘Run’ state/animation to trigger. If the movement keys are not or no longer being pressed, then the ‘Speed’ would approach zero and the ‘Idle’ state/animation will trigger. Our robot player looks a lot more lively now, don’t you think?

player_idling+running anim

I hope this week’s blog was a good read for everyone! I look forward to next week where I will finish setting up the player robot by giving it a jumping animation, fixing some ‘game logic’ issues with the robot’s speed and jumping ability, and start managing some of the game controls and general aesthetics. Stay tuned!

-Taklon