3D Platformer GameDev Series – Weekly Blog #18: Adding Enemies (Part 2)

Hello everyone. So, WordPress has released an update recently and it’s absolutely driving me nuts. Basically, I’m forced to use their “block” editor now without the means to revert to the “classic” editor. And to put it bluntly, the block editor absolutely sucks – I can’t do certain things as easily as I used to and have given up trying after spending far too much time in it. Anyway, I will continue to stick with WordPress for now (at least until I’m finished the 3D Platformer course), but there’s a good chance I might look to a different way of sharing my work down the road… Vlogging perhaps? 🙂 

Alright, so continuing where I left off last week, I will update the skeleton enemy AI today by adding additional AI states for it. No doubt, today’s post will be a little heavier on the coding side. Of course, if the coding is too much to digest, feel free to just skip to the end to see the result in the game.

Last week, in the “EnemyController” script for the enemy skeleton, the enumerated (enum) type variable was introduced (which we named “currentState”). This was used to store multiple values or states for the enemy AI. For example, the “isPatrolling” and “isIdle” states were set up such that, in their respective states, the skeleton would either be moving along a fixed path or be stopped at a patrol point along that path. Today, two additional states will be added: “isChasing” (to allow the skeleton to chase after the player when the player is close to the enemy) and “isAttacking” (to allow the skeleton to attack the enemy as long as the player is within attacking range):

And to see the skeleton’s AI behaviour in the game now, let’s take a look when the game is run:

Alright, that’s it for today’s blog – a short one, I know (to be honest, the WordPress update kind of killed my enthusiasm). Next week, I will finish updating the skeleton’s AI since, at the moment, it does not return to its chasing or patrolling states when in the attacking state. I will also make the skeleton’s attack do damage and allow the player to hurt and kill it as well. Stay tuned!

– Taklon 

 

3D Platformer GameDev Series – Weekly Blog #17: Adding Enemies (Part 1)

Good evening, everyone! After taking a break last week, I’m back this week to continue blogging my progress in the 3D Platformer course. Admittedly, I haven’t made much further progress as work has been (again or as usual now?) quite hectic. Nevertheless, today, I will be showing how to add an enemy skeleton to the game and setting up animation and basic AI movement for it.

Once an enemy skeleton model is added to the mock level/scene, the “NavMesh Building Components” for Unity are downloaded and imported into the Unity project (note that these components are separate files that are not built into Unity but are downloaded on github and imported into Unity):

SettingUpEnemyAI

Essentially, the NavMesh components allow us to easily implement AI behaviours for an enemy object. Before working on the enemy object, however, the ground is first selected and a NavMesh is generated or baked (the light-blue shaded area represents the NavMesh or area that is “walkable”):

NavMeshBake

Next, a NavMeshAgent component is added to the skeleton object, which allows it navigate the game scene/environment using the NavMesh that was generated. The NavMeshAgent also grants a whole suite of parameters to control everything from movement or steering (i.e.- speed, acceleration, etc..) to obstacle avoidance and path finding. For now, the default parameters for the NavMeshAgent will suffice. And with that, four patrol points for the skeleton are added to the scene (which serve as destination points for the skeleton to walk to one-by-one):

SettingUpPatrolPoints (game scene)

In order to setup the enemy movement (as we did with creating a “PlayerController” script for the player character at the start of this blog series), an “EnemyController” script is created for the skeleton:

EnemyControllerScript (patrolpoints)

In the script above, the patrolPoints array is of a type “Transform” which stores the position of each element in the array, or in this case, the positions/coordinates for each of the four patrol points added to the scene. Thus, the script above produces the following result when the game is run:

EnemyPatrolPoints

Now, with the enemy animations, these are set up a bit differently than the player animations. The enemy animation will be largely “state-based” to allow for implementation of state-based AI through scripting. In other words, the coding in the script will be able to dictate what state the enemy is in: attack, idle, or running:

EnemyAnimator(state based AI)

As you can see above for the enemy controller animator, the idle and running states are set up the same way as the player controller animator; that is, exit time is enabled and fixed duration is disabled. However, for the attack transition (from any state to attack) and attack to idle transition, exit time is disabled here while a fixed duration is assigned. This is because the attack state will eventually be dictated by the script (which I will learn and cover in the next blog). Hence, the ‘Attack’ parameter added is of a type ‘Trigger‘ instead (opposed to the float and bool parameters which were utilized before).

After setting up the skeleton animator, the enemy controller script is updated:

EnemyController script (AI states)_1
EnemyController script (AI states)_2

Essentially, what is happening in the script above is that the enemy skeleton is constantly switching back and forth between its ‘isIdle’ and ‘isPatrolling’ AI states. In the ‘isIdle’ state, the ‘Idle’ state is active (and the idle animation is played). In the ‘isPatrolling’ state, the ‘Running’ state is active (and the running animation is played):

SkeletonAnimationPatrolPoints

Alrighty, it’s getting super late now and I’m glad I was able to get this blog posted in time! Next week, I will set up the skeleton’s attack animation and improve its AI – for example, chasing and attacking the player when the player is nearby. Thanks for reading and stay tuned for the next blog post!

– Taklon

3D Platformer GameDev Series – Weekly Blog #15: Pause Screen (Part 2)

Howdy everyone! Today, I will continue where I left off last week in the 3D Platformer Udemy course and create the options menu for the pause screen. The options menu will basically allow the player to adjust the game’s music and sfx volume (which were implemented two weeks ago).

To create an options menu, the first step is to add a panel, “Options Panel”, to the “PauseScreen” panel. Here, another new UI element is introduced and added: the slider.  A slider is an object which contains background, fill area, and handle slide area objects (as the children); each of these contain components that allow an image and/or colour to be assigned to it:

PauseScreen (OptionsPanel)

Before diving into the scripts, there is one thing that needs to be done in Unity’s Audio Mixer window. If you recall way back when we had set up various animations for our player, we were introduced to an “exposed” parameter (i.e.- “Speed” for our character). In Unity however, some parameters are by default, unexposed. For example, the volume parameter in Unity’s audio mixer is unexposed. As such, in order to refer in our scripts to the volume parameters for the Music and SFX audio mixers, they need to be exposed and renamed:

AudioMixer (exposed parameters)

Next, the “UIManager” script is updated:

UIManager script (updated for set music+fix levels)

And then the “AudioManager” script is updated:

AudioManager script (updated for set music+sfx levels)

Before running the game, the course instructor also shows how to add a skybox and use it as a part of the lighting for the game environment/scene:

Adding a Skybox

The skybox addition is kind of a random addition, although I do recall adding a skybox in Blender before, which could really make a scene pop and stand out more! I think it also adds a bit of a realistic look to the game, wouldn’t you agree?

So it’s nearly the end of July now… As I look at the progress bar for the course, it looks like I am right at the halfway point (53 out of 108 lectures). Realistically, at this rate, I will likely finish the course at the end of the year (rather than in the Fall which I originally anticipated). I think this is fine! Looks like 2020 will be primarily about learning game development and the start of 2021 will be when I begin to design my own, original 3D platformer.

In the meantime, I hope you guys are enjoying and will continue to enjoy reading these blogs on my learning process in 2020! Next week should get more interesting as we move away from UI elements again and start learning how to add enemies to the game! Super excited for this!

– Taklon

3D Platformer GameDev Series – Weekly Blog #14: Pause Screen (Part 1)

It’s late Sunday evening as I find myself scrambling now to get this blog post published. This past week has been super busy (busier) at work. As exhausted as I have been, I contemplated on skipping this week’s blog. However, realizing that August is right around the corner, I managed to get something done in the course for this week anyhow. Today, I will add a pause menu to the 3D platformer with a button that will allow for the player to resume the game.

To create a pause menu, the first step is to create a panel (UI object), “PauseScreen”, under the UI Canvas. The colour of the panel is set to black with a ~50% opacity/level on the alpha channel:

PauseScreen (Unity)

Next, another new UI object is introduced. Here, a button (UI object) for the “ResumeButton” is added with different sprites/images assigned to the Source Image, Highlighted Sprite, and Pressed Sprite. The button is duplicated several times with the text changed for the remaining buttons: “OptionsButton”, “LevelSelectButton”, and “MainMenuButton”:

PauseScreenButton (Unity)

After, the ‘UIManager’ script is updated:

UIManager script updated (resume button)

And to set up the “PauseUnpause()” function in the ‘GameManager’ script:

GameManager script updated (pause+unpause)

A very interesting and noteworthy line of code in the ‘GameManager’ script above is “Time.timeScale“. By setting “Time.timeScale” to ‘1f’, the game runs at regular/normal speed. If it is set to ‘0.5f’, the game runs at half speed. Thus, setting it to ‘0f’ effectively pauses the game. I imagine this may be used to create some pretty cool slowdown/slow motion effects… but I’ll play around with this later probably!

Finally, let’s see what the pause menu looks like in the game:

PauseMenu (resume button)

Pretty simple, wouldn’t you agree? Next week, I shall learn to complete the rest of the buttons for the options, level select, and main menu for the pause screen. Stay tuned!

– Taklon

3D Platformer GameDev Series – Weekly Blog #13: Adding Music and Sound Effects

Hello, I hope everyone is doing well. As a recap, over the last three months, I have learned how to set up a mock level or game scene for a 3D platformer by creating: player and character movement, player health system (including death and respawn), checkpoints, health object pickup, and collectible items. Today, I will set up and add background music to the game along with sound effects (sfx) for some of the objects.

As a preface, setting up the music and sfx system in Unity is actually a tad more complicated than I expected. If there is more than one music track and sound effect in the game (which is often the case), a script will actually need to be used. Thus, to begin with, the ‘AudioManager‘ script is created:

AudioManager script

Once the ‘AudioManager’ script is created, it is attached to the “Systems Manager” in Unity. Fortunately, the rest of the work is fairly intuitive. Next, the music and sfx files are dragged into or assigned to their respective arrays:

SystemsManager AudioManager script (in Unity)

Each ‘Music Source’ or ‘SFX Source’ added to the scene has its own Audio Source component. Here, various parameters (such as volume and pitch) can be adjusted for each individual music track or sound effect:

AudioSource settings+parameters

However, there is often an additional need to control the overall volume or audio output for all music and sfx in the game as well (rather than just individual tracks and sfx). This can be done by adding an AudioMixer in Unity:

AudioMixer in Unity

Finally, to assign a sound effect to an object, the ‘PlaySFX()’ function in the AudioManager is called wherever appropriate (from other scripts). For example, in the ‘CoinPickup’ script:

CoinPickupScript (play sfx)

The appropriate sfx array element is then assigned to the game object/prefab:

AssigningSFX to object

At long last, we now have something aesthetically pleasing to the ears as well! It really makes you think how much more enjoyable having music and sound effects are in a game, doesn’t it?

And with that, it looks like the next topic in the course is to add a pause menu to the game with perhaps the ability to control some of the game settings. Thanks for reading today’s blog post and do stay tuned for next week’s!

– Taklon

3D Platformer GameDev Series – Weekly Blog #12: Adding Collectible Coins

Greetings! It has now been 3 whole months since I started my 3D platformer game development blog series! Despite some very busy work days and overtime lately in my full-time job, I feel especially proud in being able to keep up with the 3D Platformer course in my spare time, and of course, my commitment to blogging my progress in it every week.

Today, I will finish setting up the mock level (or game scene) by adding just one more pickup object to it before moving onto implementing other elements in the game such as the music, sound effects, and menu screen.

So just what is this shiny, new pickup item that will be added? No doubt, this will be a coin that the player can collect and see how many are in possession! Adding the coin is done in pretty much the same way the heart pickup was added and player health UI implemented in the last two weeks – so feel free to look back at Week #10 and #11 first if you haven’t already!

Before adding the coin to the scene (which will be done last this time), the first thing is to set up the UI to keep track of the number of coins the player has collected. To do this quickly, the ‘HealthImage’ and ‘HealthText’ UI objects in the canvas are duplicated and renamed for the ‘CoinImage’ and ‘CoinText’:

UI (CoinText+Image)

And in the ‘UIManager’ script again, a proper variable is declared to keep track of the player’s coins:

CoinTextVariable in UIManager script
AddCoins function (GameManager script)

Next, a ‘CoinPickup’ script is created for any coin objects that will be added to the scene:

CoinPickup script

A coin is then added to the game scene with a collider component, the ‘CoinPickup’ script attached, the coin value assigned, and a unique particle effect created and assigned to it. The coin is then duplicated several times:

AddCoinToScene

Alas, an animation will be added to make the coin spin. Luckily, the process of doing this is quite intuitive as the animation timeline and tools in Unity resemble very much like the ones in Flash and Blender (which I have had some experience doing animation in before):

Coin (AnimationWindow)

Taking a closer look at the timeline, the animation slider can be dragged back and forth in the timeline to see the animation play out:

CoinSpin (Animation Window)

Before running the game, I decided to add another animation for the heart pickup created earlier. Now, let’s see how the animations look in the game!

CoinAnimation (in-game)
Animation definitely adds a very lively dimension to a game, wouldn’t you agree?

That’s it for this week’s blog – I hope you enjoyed the read! As I mentioned, next week, I’ll be moving onto other aspects of the game: music, sound effects, and a menu screen. I’m quite excited for this – do stay tuned!

– Taklon

3D Platformer GameDev Series – Weekly Blog #11: Player Health UI

Hey everybody! How was everyone’s first week of summer? Any new or exciting plans out there for anyone? Myself…? Not much given that the pandemic is still very much present where I live – although places are starting to open up these past two weeks. Needless to say, I will continue each week towards my goal in completing the 3D Platformer course by this Fall. Without further ado, I will demonstrate how to update the UI to display the player’s health today.

Back at the start of Week #6, you may recall a UI object called a canvas being added to the game scene. The canvas is used to display UI elements such as the UI image for a fade in/fade out black screen added earlier. A new UI element introduced today is the UI text which is created and added to the canvas to display the player’s health points:

PlayerHealthUIText

In addition to displaying the player’s health as text, a UI image is created and added to display the player’s health bar. To keep the UI elements organized, an empty called ‘UI’ is created containing the text and image:

UI (HealthText+Image)

And as always, in the ‘UIManager’ script, variables are declared to be assigned by the UI HealthText and HealthImage:

UIManager Script (healthText+healthImage variables)

Next, similar to how an array was created in the ‘PlayerController’ script to store all the player pieces (or game objects found in the player armature), an array is created in the ‘HealthManager’ script to store all the images (or sprites) for the player health bar:

Healthmanager Script (healthBarImages sprite array)
AssignHealthBarImagesToArray

Finally, in order to update the player health points and health bar, a function called ‘UpdateUI()’ is added to the HealthManager script (see below). Appropriately, the ‘UpdateUI()’ is called in four functions within this script: “Hurt”, “ResetHealth”, “AddHealth”, “PlayerKilled” – essentially any function which would cause the player’s health to change.

HealthManagerScript (UpdateUI function)

As you can see in the script above, instead of using ‘for loops’ (as I have done all along), I learned to use “switch statements” this time –  another way to write conditional statements.

And alas, to see the player health UI (text and image) update in the game as the player takes damage, heals, is instantly killed, and respawns:

PlayerHealthUI (health display update)

And with that, that concludes this week’s blog post! I was hoping that I would have enough time this past week to move onto the next course lesson and add the next object to the scene, but work has been rather busy as usual. >< So, that will have to come about next week!

Have a good week everyone and stay safe!

– Taklon

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