GAMES DEVELOPMENT / EXERCISES

Naura / 0356798 / Interactive Spatial Design
DST61104 / Games Development
Weekly Exercises

__________________________________________________________

Week 1 : Critical reviews of our senior's existing games

Our task include:
  • Review a game from this section: https://thedesignschool.taylors.edu.my/gamezone/category/unity/
  • Get the certificate from the "Reaper Test" (optional)
__________________________________________________________

Chosen game:
Conjure by Kezia Lynn

Fig 1.1 | The starting screen of the game

Story Lore:
The game's lore is straightforward: we play as Lilith, the neighborhood witch, tasked with protecting the town of Shadowvale from the appearance of hollows. I expected each stage to progressively increase in difficulty, but instead, I found the stages becoming more confusing rather than challenging. This is mainly due to the numerous glitches and bugs that disrupt the flow of the game, especially in areas where more information about the game's setting and story should have been revealed. These issues make it difficult to fully appreciate the narrative and grasp the intended progression.

Graphics:
The game has a cohesive and appealing visual style that immediately draws you in. However, some adjustments to the color palette could enhance clarity, particularly for elements like the key in the first stage, which blends too much into the background, making it difficult to spot during gameplay.


Fig 1.2 | The key was not really visible in my opinion

Additionally, the final stage environment doesn’t quite match the atmosphere you’d expect for a boss battle setting. The shift from a dark, eerie night forest to a lighter barren cemetery doesn’t create the sense of foreboding or drama that would suit a fearsome dragon. It felt a bit underwhelming, as it didn’t convey the same intensity or danger expected from a boss’s lair. Once I completed the final stage, I was anticipating another, more challenging level or a climactic showdown. The game ending at that point felt abrupt and left me expecting more of a build-up to the true final confrontation.

Gameplay:
During the first stage, I was initially confused about how to progress. Based on an NPC's dialogue, I knew the tree was important, and I tried jumping over it, but it wasn't clear that it needed to be destroyed until a few minutes later. A clearer indication of what the player needs to do could improve the experience here.


Fig 1.3 | NPC dialogue is not visible

Moving to the second stage, I encountered several bugs. One notable issue was with the NPC dialogue, which didn’t display correctly even in full screen mode, leaving me to guess the objective. During my first run, I killed an NPC for meat, but when I wandered too far to the left, I fell off the screen and had to restart the game entirely. It seems the tree at the far end was intended to act as a boundary, but it wasn’t properly coded to prevent this from happening. Another issue was being immediately attacked by a red ghost as soon as I reached stage 2—if your reflexes aren’t quick, you’re caught off-guard right away.

Additionally, I didn’t notice a significant difference in difficulty between the gray and red hollows. While the red hollows are faster and have a longer attack range, it doesn’t feel much different in practice because Lilith’s attack range is so long that I could simply spam the "Z" key from one side of the screen and still hit the mobs that were off-screen. This makes it easy to defeat them without feeling the increased challenge that the red hollows are supposed to present.


Fig 1.4 | The boundary was not boundary-ing

As for the boss stage itself, while there were minor bugs, I actually enjoyed the challenge of the platforms disappearing after a few seconds—though I’m not sure if that was intentional. One issue I noticed was that the ghost enemies could float over the platforms and hit you even if you were standing in the middle, which seemed more like a glitch than a design choice. Additionally, I lost a life without even touching the boss dragon, which was frustrating. It would also be helpful to have a health bar for the boss to track progress, and it would add to the immersion if the full dragon were visible, as I could only see its lower body.


Fig 1.5 | Completed the game

Audio:
I appreciate how the background music varies across the three stages, adding distinct atmospheres to each level. However, I think the final stage needs a more intense soundtrack. The current soft instrumental music feels too relaxing and doesn’t capture the tension or urgency expected in a boss battle.

The attack sound effects are well done and satisfying, but they can sometimes overpower the background music. It would help to balance their volume so that both elements complement each other. I also enjoyed the cute sound effect when the character jumps—it suits the personality of a young witch like Lilith. One suggestion for improvement would be to add a "pain" sound effect when monsters take damage, as the only indication that they’ve been hit is the appearance of blood droplets. For the boss battle specifically, adding a distinct sound or visual effect when the boss is injured could better differentiate its difficulty from regular mobs and create a stronger sense of impact during the fight.

I also managed to beat the Grim Reaper game (it was hard).


Fig 1.6 | I'm a certified Grim Reaper

My thoughts:
Overall, I think it's a solid and simple game with great potential, especially in terms of lore. With more time and refinement, these issues could be ironed out to create an even better experience. By critiquing our senior's game, I’ve learned how design choices—such as unclear objectives, mismatched soundtracks, or unbalanced difficulty—can impact a player's experience. This observation helps me understand how to create a more intuitive and engaging game for my own assignment in the future. Being able to identify these elements allows me to approach my own game design with a more critical and player-centered perspective, ensuring that my game’s mechanics and storytelling resonate better with players.

__________________________________________________________

Week 2 : Game Ideation

Our task include:
  • As a group, use the SCAMPER method to develop your own unique game concept. Ensuring to include the;
    • Story
    • Gameplay
__________________________________________________________

As a group of 5, we began by brainstorming the types of games we used to play, like Subway Surfers, Dress Up Barbie, and Papa's Pizzeria. However, we soon realized that there were already too many variations and sequels of Papa’s Pizzeria, making it difficult to come up with something truly unique. As for Subway Surfers, it’s a 3D endless runner, which would have required a more complex game design and mechanics. After narrowing down our options, we found that Plants vs. Zombies offered a balanced mix of strategy and simplicity, making it the ideal base for using the SCAMPER method to create something fresh while keeping the design manageable.


Trying to come up with something unique using the tower-defense game concept was challenging, but not as challenging as the other games we initially suggested. Throughout our discussion, we kept throwing around crazy ideas until someone would go, ‘OH WAIT! That could work!’—and that’s how our brainstorming dynamic really started to click. 


Initially, the lore of our game was almost identical to Plants vs. Zombies. The only twist was that we, the players, were allergic to dogs, so it was up to the cats to fight for us! It was all a bit silly, but then Natania came up with the idea of making the animals deities, adding an interesting twist. We started incorporating real-life characteristics of cats and dogs into the game design, like cats being super prideful and dogs being playful, which made the concept even richer and more engaging.


Personally, the most intriguing implementation we came up with was the environmental hazard obstacles. Since our game is set in the skies, weather conditions like rain, wind, and snow can drastically impact our cats' performance. For example, rain slows down both cats and dogs, making it harder for them to move across the battlefield. Wind, on the other hand, can randomly blow away weaker cats, making certain paths riskier to navigate. Meanwhile, snow decreases the speed of our cats' attacks and makes them more vulnerable to enemy advances. These environmental factors add an extra layer of strategy, forcing players to adapt their tactics to the ever-changing weather conditions.

My thoughts:
To conclude, I had never heard of the SCAMPER method before, but using it to transform an existing game into something original demonstrated how an established concept can be creatively reimagined. I believe this framework will be helpful for my upcoming assignment in the upcoming weeks

🡐 Back

__________________________________________________________

Week 3 : Introduction to UNITY

What we did:
  • Replicate Angry Birds game mechanics by creating a catapult to fling an object to crush a set of obstacles.
  • Using the package 3D assets provided, create a game where the player controls the car to avoid obstacles
  • Tackled an additional challenge to further refine our Unity skills.
__________________________________________________________

In the first exercise, we learned about essential Unity components: Rigidbody—enabling GameObjects to interact with physics like gravity and collisions, and Collider—defining the shape for detecting and responding to collisions with other objects.

We then applied these concepts in the exercise shown below:


Fig 3.0 | My rendition of the introductory exercise

Fig 3.1 | Gameplay of the First Exercise

Next, we were introduced to 3D Unity. According to Sir Razif, gaining early exposure to this tool is beneficial since the game industry is increasingly leaning towards 3D development. He suggested that we learn the fundamentals now to stay ahead in the future. To support our learning, he also provided us with a PDF guide, ensuring that no one falls behind during the exercise.

Fig 3.2 | Chapter 1 PDF Instructions

Here is the result of my 3D exercise:


Fig 3.3 | Gameplay of the 3D Exercise

The most challenging part of this exercise was definitely getting the camera to follow the vehicle using the FollowPlayer script. I think most of my coursemates would agree, as we spent a lot of time troubleshooting what could have gone wrong. But in the end, we managed to figure it out together!😊

After that, we were asked to tackle the plane programming challenge (page 29 of the PDF). I found this challenge to be relatively straightforward since most of the script could be adapted from what we previously worked on as a class. The only new aspect was getting the propeller to rotate. However, the toughest part for me was adjusting the camera. It required a lot of tweaking because I initially thought it could be resolved through the FOV settings, but I ended up making some changes to the script as well. The video below shows my final result:

Fig 3.4 | Gameplay of the Plane Programming Challenge

My thoughts:
From this exercise, I learned how to implement basic player controls in Unity, such as creating C# scripts to move a vehicle and making adjustments to camera movement. It also helped me better understand how to structure scripts and tweak variables to achieve desired effects.

Playing around with Unity taught me that it’s not AS EASY as it looks. There’s a lot of trial and error, especially when trying to achieve smooth movements and interactions between objects. 

🡐 Back

__________________________________________________________

Week 4 : The pain of UNITY continues...

What we did:
  • Complete the Chapter 2 starter exercise using the provided assets, focusing on key concepts such as Colliders, Prefabs, and other elements.
  • Apply the knowledge gained to tackle the subsequent challenge, reinforcing and expanding upon the skills learned during the exercise.
__________________________________________________________

We did Chapter 2 of Unity which introduce us to other coding gameplay elements such as if-elif-then statements, random value generation, arrays, collision detection, prefabs, and instantiation (I got programming war flashbacks omg). It was fairly simple, offering just the right amount of challenge, even with the help of the provided PDF instructions.

Fig 4.0 | Chapter 2 PDF Instructions

I believe the problem-solving started when we tried to destroy the animals, but my friend and I were confused as to why they wouldn’t disappear. We tinkered with the scripts, dragging the DestroyOutOfBounds script to the game objects, hoping it would work. Then I recalled from last week that both game objects need colliders, and I realized my food projectiles didn’t have them (LOL).

I'm relieved and happy that it worked, but I’m not sure why certain animal prefabs won't get destroyed unless the projectile hits the exact center of the animal game object. As you can see below, some of my horses or chickens don’t get destroyed, even if the projectiles hit them, and it takes several projectiles before they finally disappear, even though it was working fine earlier.

Fig 4.1 | My Starter Exercise Overview 

For the challenge, I noticed that the game is very similar to our starter exercise because the C# scripts were almost identical to what we had in the starter exercise.

The first issue I tackled was that the player was spawning balls (that sounds wrong but I have no idea how to word it better) instead of dogs in the player controller. To fix this, I updated the game object to spawn dogs instead of balls.

Next, I noticed no balls were spawning from the top, and I realized the SpawnManager didn't have any ball prefabs attached. I added the ball prefabs provided to resolve this.

When testing the game, I saw that even if the ball didn’t touch the dog, it still disappeared. Upon checking, I found the dog's collider was far larger than the actual game object, so I adjusted the collider to fit the dog properly.

Another issue was that only ball 1 (the blue one) was spawning. After comparing with the starter exercise, I found that the code was always instantiating the ball at index 0 of the 'ballPrefabs' array, causing only one type of ball to appear. To fix this, I adjusted the code to use 'ballPrefabs[ballIndex]'.

To make the spawn interval random, I implemented a delay between 3 and 5 seconds using 'Random.Range(3f, 5f);' after 'SpawnRandomBall()'. I removed InvokeRepeating() since it doesn’t support dynamic intervals and replaced it with 'Invoke("SpawnRandomBall", randomInterval);', which schedules the next ball spawn after the random delay.

Lastly, while reviewing the challenge video, I noticed it also included a "Game Over!" debug message, so I added that as well. I also adjusted the bottom limit of the game to -13 (the position of the ground game object) instead of the original -5 , and updated 'transform.position.z' to 'transform.position.y' where necessary.

Fig 4.2 | My Chapter 2 Challenge Gameplay

My thoughts:
This challenge taught me to be more detail-oriented as I worked to spot the differences between two codes. It was actually enjoyable, probably because the game ended up working fine... I know it wouldn’t have been as fun if it hadn't!

🡐 Back

__________________________________________________________

Week 5  : Sound Effects and Animation

Our task include:
  • Refer to the PDF instructions to guide the game development process.
  • Attempt the challenge to test your understanding and skills.
__________________________________________________________

Chapter 3 of Unity dives deeper into complexity, focusing on animations and sound effects. When I first skimmed through the PDF, I expected to code the animations myself TT—but thankfully, Unity simplifies it with the Animation Controller (though it’s still challenging since there’s plenty of coding involved).

Fig 5.0 | Chapter 3 PDF Instructions

And just when you think you’re done tweaking the PlayerController code... WAIT, there’s more! AHAHAHAHAH (yes, I went insane). Adding these effects definitely made the game more engaging, but it’s a whole new level of work!

Fig 5.1 | Starter Exercise Outcome

To tackle the challenge, the first issue was that pressing the spacebar didn’t make the balloon or player float upward. I managed to fix this in the code, though I can't recall the exact change, but it worked as intended, aha.

Next, I noticed the background looping was choppy, so I modified 'repeatWidth = GetComponent<BoxCollider>().size.y / 2;' to 'repeatWidth = GetComponent<BoxCollider>().size.x / 2;' for a smoother loop.

I then updated 'InvokeRepeating("PrawnsObject", spawnDelay, spawnInterval);' by renaming "PrawnsObject" to "SpawnObjects", which now triggers the spawning of bombs or money objects every few seconds.

To correctly position the fireworks display at the balloon's location, I set the x position of the visual FX to 0  in the Inspector.

I added 'public float maxHeight = 13.0;' to define a maximum height for the background. Alongside '!gameOver', I included 'transform.position.y < maxHeight' to prevent the balloon from floating too high.

Finally, to make the balloon appear to bounce off the ground, I added 'private float minYPosition = 1.0f' and 'private float bounceForce = 10.0f'. For the sound effect on bounce, I included 'public AudioClip bounceSound;'. After adding the AudioClip, I dragged the "Boing" sound effect into the player object to ensure it would play. Here’s the code to make the balloon bounce and trigger the sound when it hits the minimum Y position:

if (transform.position.y < minYPosition && !gameOver) 
{ 
    playerRb.AddForce(Vector3.up * bounceForce, ForceMode.Impulse);
    playerAudio.PlayOneShot(bounceSound, 1.0f);
}

Here is the Outcome for Chapter 3's Challenge (Don't mind the aggressive space bar sounds):

Fig 5.2 | Challenge Chapter 3 (short) Gameplay

My Thoughts:

This chapter was a whole new level of coding. One thing that stood out was definitely the iterative nature of game development. Just when I thought I’d finished adjusting the PlayerController code—surprise! There was more to do. This process tested my patience but also reminded me how small adjustments can make a huge difference. Implementing animations and sound effects not only made the game more immersive but also brought a new level of enjoyment to the work. Watching the game come to life with these added effects made me appreciate how important these elements are in enhancing the player experience.

🡐 Back

__________________________________________________________

Week 6 : Power ups and Wave Difficulty

Our task include:
  • Program an arcade-style sumo battle where the goal is to knock enemies off a floating island.
  • Create increasingly challenging enemy waves to test player skills.
  • Integrate power-ups to assist in defeating tougher enemies.
  • Complete the challenge to apply and reinforce skills learned in Chapter 4.
__________________________________________________________

Chapter 4 walks us through programming a powerup that provides the player with a temporary advantage, along with coding progressively tougher enemy waves to make survival more challenging.

Fig 6.0 | Chapter 4 PDF

Here’s my gameplay from the starter exercise. It took a while because I found the controls frustrating—I really don’t like that we can’t adjust the player's horizontal movement force...

Fig 6.1 | My Chapter 4 Gameplay Mechanics

Next, I took on the Challenge, applying what I learned from the starter game. To address the first task, I modified the PlayerControllerX script. In line 60, I changed 'Vector3 awayFromPlayer = transform.position - other.gameObject.transform.position;' to 'Vector3 awayFromPlayer = (other.gameObject.transform.position - transform.position).normalized;' to ensure the enemy is pushed directly away from the player.

When testing, I noticed that after defeating all enemies, a new wave didn’t spawn. To fix this, I updated the SpawnManagerX script by changing the tag from "Powerup" to "Enemy" on line 23 to properly track active enemies. However, at this stage, the game still spawned only 2 enemies per wave ( just a note to myself).

I then addressed the power-up cooldown. Although the script had a cooldown setup, it wasn’t triggered when picking up a power-up. To fix this, I added 'StartCoroutine(PowerupCooldown());'  after the  'powerupIndicator.SetActive(true);' line.

I made adjustments to ensure the correct number of enemies spawn with each wave. To achieve this, I moved waveCount++ from within the SpawnEnemyWave(int enemiesToSpawn) method to the Update() method, placing it just after 'SpawnEnemyWave(waveCount);'. This way, it can spawn an increasing number of enemies based on the current wave number. Additionally, I modified for '(int i = 0; i < 2; i++)' (which means it'll always spawned two enemies) to 'for (int i = 0; i < enemiesToSpawn; i++)', ensuring the correct enemy count per wave.

To make the enemy balls target the 'Player Goal' object, I updated the EnemyX script. I added 'playerGoal = GameObject.Find("Player Goal");' in the Start() method, which ensures each enemy locates the 'Player Goal' GameObject. Lastly, I set the enemy speed to 25 in the Inspector for a better pace as it's not too slow nor too fast.

For the bonus challenge to activate a speed boost by pressing the spacebar, I added the following lines of code to the script:

Fig 6.2 | Field Declations in PlayerControllerX

Fig 6.3 | SpeedBoost Coroutine in PlayerControllerX Script

For the final bonus challenge (FINALLYY), I modified the SpawnManagerX script to increase enemy speed with each new wave.

I added the following line:

EnemyX enemyScript = enemy.GetComponent<EnemyX>();
enemyScript.speed += waveCount * 0.5f;

Since I'm already setting the enemy's initial speed directly in the EnemyX script through the Inspector, I realized I don’t actually need a separate enemySpeed variable in SpawnManagerX. Instead, I could adjust the existing speed variable in EnemyX directly to increase it with each wave.

However, I encountered an error that said 'enemy' does not exist in the current context (oops!). So, I asked ChatGPT for help, and here are the changes I made based on that guidance:

Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
EnemyX enemyScript = enemy.GetComponent<EnemyX>();
enemyScript.speed += waveCount * 0.8f;

into

GameObject enemy = Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
EnemyX enemyScript = enemy.GetComponent<EnemyX>();
enemyScript.speed += waveCount * 0.8f;

Fig 6.4 | Challenge 4 Gameplay (2 mins long)

My Thoughts:
Reflecting on this, my initial reaction was simply, "wow… the code just keeps growing." Yet, I’m genuinely thankful for this chapter—it dives into a game mechanic that I’ve wanted to bring into my own project. I can see how much value this chapter holds, and I’m sure I’ll be coming back to it often when I’m deep in the coding stage. It’s been a valuable learning experience, for sure.

🡐 Back

__________________________________________________________

Week 7 : Building the Game Prototype

Our task include:
  • Apply the knowledge gained from the first four chapters of Unity to create and develop a 2D game, which can act as the foundation for your game prototype
__________________________________________________________

The initial step involved creating a basic player sprite along with the ground, ensuring they had the necessary components like Rigidbody2D and a Collider (adjusted based on shape). During the first hour of the lesson, we focused on making the player move left and right and added a jumping function. We also fine-tuned the settings to prevent the player from appearing as if it’s floating during jumps. Finally, we implemented a double jump feature, ensuring that the player could jump twice but not continue with additional jumps beyond that.

After a break, we added a door that disappears when the player enters a specific area. However, Sir Razif then modified this feature to include an opening and closing animation for a smoother user experience. We also introduced a coin feature that vanishes when the player collects it. 

Here's how the gameplay looks:

Fig 7.0 | Gameplay Overview

My Thoughts:
It's nice to see that, even though we spent the past few weeks learning Unity in 3D, it's fascinating how those same concepts can be applied to 2D with only minor adjustments, like remembering to use "2D" after components such as Rigidbody. I'm so used to working with 3D where it's just Rigidbody without the "2D," so this shift was an important detail to remember. Implementing these familiar concepts in a 2D space has been a great experience, and I think I would definitely incorporate the double jump feature in my own game for added complexity and fun gameplay.

🡐 Back

__________________________________________________________

Week 9 : Visual Integration

Our tasks include:

  • Creating and managing game-related states such as currencies, collected items, health, bullets, and more.
  • Designing and implementing the Game UI, including game screens, navigation, and HUD integration.
__________________________________________________________

Week 9 builds upon where we left off in Week 7, as we continue developing a game prototype that combines everything we’ve learned so far. 

We started by downloading a set of files containing various sprites, such as coins and power-ups, which also included their animations. The first task was to replace the coins implemented in Week 7 with the animated versions. This added an idle animation to the coins instead of leaving them static. We also created keyframes for the coins disappearing when collected by the player. (At this point, I’ll admit, I was already feeling a bit lost!)

Next, we worked on implementing the HUD to display the number of coins the player had collected. Sir Razif also adjusted the virtual camera, but I realized I hadn’t set up the virtual camera during Week 7, so I had to quickly install and integrate it into my hierarchy. Once that was done, we anchored the coin collection HUD to the top-right corner of the screen.

Since I had used different GameObject names and tags in Week 7 compared to Sir Razif’s setup, I had to constantly remind myself to reference my own naming conventions. This was a bit of a setback, but it was a good learning experience in debugging and adapting code to my setup.

At one point, I encountered an error where the GameData class was defined multiple times, which confused me because Sir Razif didn’t have this issue. After some troubleshooting, I realized I had accidentally duplicated the GameData class while moving it to the Scripts folder. Once I deleted the duplicate, the error was resolved.

Later, we added a feature where the door would only open if the player collected 3 coins. However, this mechanic was revised to spawn a gem key after collecting 3 coins, which the player could then use to unlock the door. I ran into an issue here when I renamed the script for the gem key and tried adding it to the Prefabs folder, only to get an error saying the MonoBehaviour didn’t exist. I even tried renaming it again in the script file, but the problem persisted. In the end, I restarted the script from scratch, and it finally worked! (This was definitely one of those moments where even ChatGPT wouldn’t have been much help!)

We also replaced the old door with a new one that had an animated opening transition. The animations were pre-made, so we just had to assign them in the animation box. To complete the feature, we made the door’s box collider disappear when fully opened, allowing the player to pass through.

Finally, Sir Razif introduced a mechanic inspired by Spider-Man, where the player could cling to walls and jump between them. I added this mechanic and adjusted my level layout to include a section where the player must use this ability to collect coins and the gem key, which were placed beyond these wall-jumping obstacles.

Below is my outcome:

Fig 8.0 | The Outcome

My thoughts:
This week was a mix of technical challenges on my part... I definitely learn more on adapting when things didn't go as planned. From resolving the GameData duplication error to troubleshooting issues with the gem key prefab, I learned to be patient and persistent. Also I get to learn about the game UI which is what I would include in my own game anyway since I need a system that provides immediate feedback for player interactions.

🡐 Back

__________________________________________________________

Week 10 : Player and Enemy Animations

Our tasks include:

  • Transform your capsule player into a fully animated character.
    • Insert idle animation.
    • Insert attack animation.
    • Insert jump animation.
  • Create and animate an enemy character.
    • Add idle animation.
    • Add hit (damage) animation.
    • Add death animation.
__________________________________________________________

During our class tutorial and practical session, we focused on tweaking our Unity project from last week. This time, we replaced our initial placeholder player with a real character, complete with idle, attack, and jump animations. One of the challenges we faced was ensuring the attack animation didn’t loop unnecessarily and adjusting its speed to make it look natural—neither too fast nor too slow. I think we all struggled with this part a bit, but it was satisfying to learn that tweaking options like exit duration helped fix the issues.

For the enemy, we added idle, hit, and death animations. We took it a step further by adding a fade-out effect for the death animation, rather than having the enemy disappear instantly, which made the transition feel much smoother.

Below is my outcome:

Fig 9.0 | Week 10 Gameplay Outcome

My thoughts:
Thank goodness we went over this in class! I wasn’t sure what I was doing wrong when inserting my player animations into the game, but now I know where to debug and adjust settings to prevent issues like looping. That’s such a relief. I’m still a bit confused about some aspects of the Animator, but I’m eager to keep learning and improve!

🡐 Back

Comments

Popular Posts