3D Platformer GameDev Series – Weekly Blog #10: Health Pickup and Particle System Effects

Oh my… the weeks sure are rolling by. I am now about one third of my way through the 3D Platformer Udemy Course! Today, I will add another object to the game scene for player health pickup. Afterwards, I will revisit the particle system and use it to create some interesting effects when the player is killed.

If you have read my last few blog posts in previous weeks, you should know by now how game assets or objects are added into Unity and programmed to interact with the player. Just like the checkpoint or the spike trap added earlier, a game asset of a heart container for the health pickup is added into the game scene with an appropriate-sized collider for the player to potentially enter:

HeartPickup (add to game scene)

In the same way the checkpoint and spike trap were set up, the ‘Is Trigger’ on the ‘Health Pickup’ collider is enabled to allow the following ‘HealthPickup’ script attached on the object to work:

HealthPickupScript

And in the ‘HealthManager’ script, for the “AddHealth” function:

HealthManagerScript (addhealth function added)

As you can see above, the coding and logic for the health pickup is very straight-forward. The result when the game is run, is thus, rather simple (the heart disappears when the player walks over to it and the player is healed):

HealthPickup

Next, it is time to revisit Unity’s built-in particle system. This was used a few weeks back to generate lights to appear from an active checkpoint. Today, the particle system will be used again to create a death effect for the player when killed. In order to do this, the following code is first entered into the ‘GameManager’ script (see yellow and green boxes):

GameManagerScript (updated for player death effect)

Here, a new method called “Instantiate” is introduced above. Instantiate means to create a copy/clone of any object or any prefab (in or outside of the game scene), returns it, and allows the copy to appear at a newly specified location and rotation. Already, I can think of so many ways the instantiate method can be used in game development; from inventory systems to character customization to enemy transformations, I anticipate this will be a method I will utilize more and more in my game development endeavours.

Now, back to Unity. After setting up the script, the next step is to create a particle system effect (two systems grouped together make up the effect here):

PlayerDeathEffect object (particle system)

As you can see, there are a lot of different parameters to adjust and play around with in Unity’s particle system to achieve a desired or intended effect. For the player death effect, general parameters that are changed include the Duration, Looping, Start Lifetime, Start Speed, Start Size, 3D Start Rotation, and Gravity Modifier. Various parameters within the following are also added, taken away, changed, and/or adjusted: Emission (burst time, number of particles, etc..), Shape (the shape of the volume in which particles are emitted; i.e.- spherical), Size over Lifetime (particle size from beginning to end; i.e.- linearly big to small), Collision (physics can affect particles), Renderer (how the particles are rendered; i.e.- particles are cubes).

After creating the ‘Player Death Effect’ prefab, it is assigned to the ‘deathEffect’ variable in the ‘GameManager’ script that was set up earlier:

PlayerDeathEffect (assign in game scene)

Alas, to see how the effect looks in the game:

PlayerDeathEffect (in-game)

I must admit, lately I have been coming up with some ideas for a 3D platformer now that I have a little bit of development knowledge for the genre. This may be premature of me to say, but I really hope that I can finish this course by September or October. In effect, that will leave me with a bit of time until the end of the year to come up with a simple and fun design for a game to develop next year. My goal is to create an original 3D platformer in 2021 while continuing the weekly blogs to share my development process  for it (which would include any and all struggles along the way… *nervous chuckle*).

Anyway, I hope you enjoyed the (longer) read this week! Stay tuned for next week when I learn how to update the UI to display the player’s health and add another new object to the scene! Can you guess what that object would be? 🙂

– Taklon

3D Platformer GameDev Series – Weekly Blog #9: Player Invincibility

Howdy all! I hope everyone’s been doing well and perhaps finding their own ways to navigate through these times. For me, working on the 3D Platformer course and writing these weekly blogs have helped me relieve some of my recent stresses at work. I highly recommend others to do the same and perhaps even start their own blogs. If anyone does happen to blog, do let me know in the comments as I would love to see what you have to share with the world!

Alrighty, let’s get right into this week’s update on the 3D Platformer Course, shall we? After learning how to implement player knockback last week, the next thing to do today is to grant the player invincibility after getting hurt or taking damage.

We begin with the HealthManager script that we started last week:

HealthManagerScript (implement invincibility)

And to see it in action against the spike trap we added to the scene last week:

PlayerInvincibility

Looks good! However, there are many ways to show or represent invincibility in games. One of the simplest tricks is to make the player flash for the duration of the invincibility. This is simply done by programming the player to hide and unhide repeatedly. Still, the approach in Unity is a bit tricky. The first step is to create an array in the ‘PlayerController’ script to store all the “pieces” (or objects) found in the player armature:

PlayerPieces array (PlayerControllerScript)PlayerPieces (for invincibility flashing)

You may recall a few weeks ago when we created an array to find all the checkpoints in the scene – well now, we will use the array and update the ‘HealthManager’ script:

HealthManagerScript (showing invincibility by player flashing)

What’s noteworthy perhaps in the script above is the use of a math function called “Floor” (rounds the result down to the nearest whole number) and a computing operation called “modulo” (divides a number by a specified number – 2 in this case – and gives a remainder); these are used to perform a check on whether a number is an even or odd number. Little did I realize I have come to understand the following: Yes, understanding math may not be essential to game development – however, it sure makes a lot of cool and powerful things happen more easily!

And so, here is the end result of player invincibility and flashing:

PlayerFlashingWhenInvincible

That’s it for this week’s blog post! Thank you for reading, as always. Stay tuned for next week when I learn to complete the rest of the health system!

– Taklon

3D Platformer GameDev Series – Weekly Blog #8: Health System and Player Knockback

Hey everyone! Whoa… It’s been about two months since I started this weekly blog series and the 3D Platformer Udemy Course. I feel that I am now heading into the bulk of the course material where the coding and logic is starting to get a bit more complicated to grasp – you may realize this too (if you have been following this blog series all along) when I attempt to explain how to implement player knockback today.

Before I dive right into the main content of my post, there is a key concept that I would like to mention again as it is becoming more evident when making a game in Unity and programming in C#:

“Individual scripts should only handle their individual elements.” – James Doyle

This concept was introduced earlier when the ‘GameManager’ script was created. You may recall that this script deals with everything that happens at the broader game level. However, that’s not to say that we cannot create – as we have done – instances of individual scripts and functions within them to call or be called by other scripts. We saw how important this was for the first time when player respawn was implemented and then again when checkpoints were added. This keeps the script and coding logic much more easy to read and follow! So as I progress further in the course, I will point this out less; by now, you should be able to see clearly how scripts, in a sense, interact with one another.

Now, onto the main topics of this post. The first thing is to create a health system. While it may be tempting to create it in the GameManager script, as I had just reminded everyone, we would want a separate or individual script for handling and managing the health system instead:

HealthManager script

The health system is really simple to set up as you can see from above. And because the script is set up as an instance, the ResetHealth function can then be called in the ‘GameManager’ script whenever the player respawns:

GameManager script updated

Now, something is needed to reduce the player’s health and to call the ‘Hurt’ function in the HealthManager script. For this, let’s add a spike trap to the game!

Spikes (add to game scene)

Just as we did with the Killzone created earlier and the checkpoints added before, for an interactable object such as these spikes, a box collider is added and the “Is Trigger” enabled to allow the following “HurtPlayer” script attached to the spikes object to work:

HurtPlayer script

Excellent! The only thing left to do now is to set up the player knockback when the player gets hurt. For this, we turn back to the ‘PlayerController’ script. Yes, you read right… I didn’t think we would have to turn back to the PlayerController script either…

PlayerControllerKnockBackPart1
PlayerControllerKnockBackPart2

Oh my… Did you understand all of that? It took some time for me afterwards, but if I were to try to come up with this logic myself, I honestly don’t think I would have been able to. And as an aside, this is one thing that especially bothers me sometimes. That is, for someone like myself who is not naturally good at programming and logic, it bothers me when I understand some aspect of coding only afterwards in hindsight. Although, I do believe that there are always more than one ways of doing or solving something. That being said, can anyone think of another way to implement player knockback? 🤔

PlayerKnockback

Anyway, that’s it for this week’s blog! I hope you enjoyed the read. Stay tuned for next week when I make our robot player temporarily invincible and flash after getting hurt!

– Taklon

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

 

 

My First Game Jam Experience!

Hey everyone! In my previous blog post, I mentioned that I had joined my first ever game jam with an ol’ buddy of mine! I figured that instead of a written blog post about my first game jam experience, I’ll do a vlog instead! Here it is (I recommend watching in HD and fullscreen if possible):

After participating in this jam and using all the artistic knowledge and skills I have gained in the past year (since I started writing this blog), I now have a better understanding of where my strengths and weaknesses lie in 3D modelling and animation in Blender – and how that translates to other areas/fields such as game development. You see, this game jam had pressured me to churn out work rather quickly in order to meet a strict deadline and also forced me to come up with a compromise between quality and quantity of the game assets themselves. And while it was a bit stressful at times, it was also rather satisfying and a lot of fun!

No doubt, I may yet participate in another game jam before the end of this year! We shall see…

– Taklon

GameDev Blog #3: Basic Items, Equipment, and Inventory System

After implementing walk and run movement for our player, I started creating some basic interactable objects which would also show up as items in a player inventory system. In addition, I made a few simple pieces of equippable items such as clothes.

So far, I am trying my best to spend a minimal amount of time working on the aesthetics and UI for 2D/3D models and sprites since they can be re-designed and/or their level of detail can be raised later. Instead, the bulk of my time has been used towards primarily completing all the functional systems (e.g.- player movement, inventory, combat, etc..), and of course, a lot of time is spent constantly debugging and trying to get things to import and work properly in both Blender and Unity.

Interactable Environment Object

blueherbBlue herbs can be picked up in the game scene/environment. Once picked up, they appear in the player inventory. Later, they can be used as a consumable item to restore  some of the player’s health.

itempickupandinventorysystem

Equippable Items/Equipment

vagabondshirtA simple, default equippable shirt for the player.

vagabondpants
A simple, default equippable pair of pants for the player.

equippingclothesEquipment will appear on the left-side in the inventory once equipped (this will be implemented at a later point). For the next update, I will add a basic weapon and design an enemy to prepare for the combat system.