3D Platformer GameDev Series – Weekly Blog #21: Adding Enemies (Part 4)

Hello everyone! Today, I will complete the last lecture on “Enemies” in the 3D Platformer Course. Last week, we finished implementing the enemy skeleton’s attack, allowing it to deal damage to the player. However, on the other hand, the player is currently unable to defeat the skeleton.

In many 3D platformers, one of the primary ways for the player to defeat enemies is to jump on them. Primitive, I know, but functionally useful so it makes sense to learn how to do this! Thus, this will be the main focus of today’s blog post.

To implement the player’s ability to attack by jumping, two hitboxes are created. The first hitbox is located at the top of the enemy skeleton’s head:

The second hitbox, named “Enemy Hurtbox”, is created and positioned at the player robot’s feet. Here, a rigidbody component is further added to it, allowing this hitbox to interact with the skeleton’s hitbox:

A new script named, “HurtEnemy”, is then created and attached to the “Enemy Hurtbox” on the player:

Another new script named, “EnemyHealthManager”, is created and attached to the skeleton. This script contains a function called, “TakeDamage()”, which is called by the “HurtEnemy” script created prior:

When the game is played, we can see that the enemy skeleton disappears as soon as the player jumps on its head:

In order to improve the aesthetic of the skeleton’s death, three things are done: playing a death sound effect, making the player bounce up after landing on the skeleton’s head, and leaving behind a particle effect. Implementing the above makes sense as we have learned how to do all these things before: playing a sound effect when collecting a pickup back in weekly blog #13, adding a knockback to the player when taking damage in weekly blog #8, and leaving behind a particle effect when the player is killed in weekly blog #10.

To create the bounce-up effect, a simple function similar to the player knockback is added to the “PlayerController” script:

Next, the “EnemyHealthManager” script is updated to call the “Bounce()” function. In addition, two simple lines of code generate the enemy death sound effect and particle effect:

By tweaking the player’s death particle effect and applying it to the skeleton, we can see that the player’s jumping attack on the skeleton is now much more interesting than before:

Last but not least, to reward the player for successfully jumping on and killing an enemy, a new coin prefab (a silver coin) is first created from the coin added earlier in weekly blog #12. The “EnemyHealthManager” script is then updated in order to instantiate the silver coin appropriately:

Lo’ and behold, here is the in-game result for killing an enemy skeleton:

That’s it for today’s blog post – which also wraps up the course section on “Enemies” in the course. Believe it or not, today is a major milestone in the course as we have all the game assets necessary now to start making actual levels/stages! No more mock game scene, woot woot!

Indeed, the next section of the course will look at designing levels – no doubt, I will get a chance to design my first level for a 3D platformer! I’m very excited about this… Stay tuned!

– Taklon

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

Hey everyone! I apologize as it’s been nearly a month since my last blog post – I have simply been preoccupied with things other than game development. But, the important thing is that I still intend on completing the 3D platformer course by the end of this year. As 2020 unwinds, I have to put a bit more of my spare time into the course over the next few months. With that, let’s jump right into Unity and continue where we left off with our enemy skeleton.

After setting up the AI states for the enemy skeleton earlier, one final thing that needs to be done is to return the enemy skeleton to its patrolling state when it’s in the attacking or chasing state and the player is no longer within attacking or chasing range:

Behold, the fully-implemented AI states of our enemy skeleton in the game:

Next, we will create a hitbox for the enemy skeleton’s attack. A hitbox is an invisible, defined area whereby damage is incurred. In this case, a damage hitbox is added and activated in the skeleton’s attack animation (as soon as the skeleton begins to attack) and deactivated when the skeleton completes its attack. If the player is inside the hitbox, damage is done to the player (via the “Hurt Player” script which was created earlier when the player health system was implemented):

Let’s now see the skeleton’s attack causing damage to our player in the game:

That’s it for this week’s blog! I hope you enjoyed the read. Next time, we will implement a way to allow the player to kill the enemy skeleton. It wouldn’t really be fair otherwise, right? 😉 Upon killing the skeleton, this would further spawn coins for the player to collect! Stay tuned!

– Taklon

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 #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 #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