Game Flow
Intro to Game Flow
Group Project initial concept idea
First week of Game Flow was to introduce us to what we are going to learn.
For this module we are actually grouping together to make a game in Unity, which I am ecstatic about.
One of the things that we are going to do in the context of this is learning C#, a programming language in the .Net platform.
Personally I find programming a bit scary but taking it as a challenge makes it more exciting. Will take it as Dark Souls boss, fail multiple times until I make it!
During this lecture we formed groups of 2-3 and started coming up with ideas for the game we would be making during the duration of this module.
We were given the theme "Childhood".
As a group we thought of 4 concept ideas:
|
|
|
|
|
|
|
|
|
|
|
1 - Sneak out of the House
Player is a child that needs to sneak out of the house without getting caught
|
|
|
|
|
|
|
|
|
|
|
2 - Ice Cream Truck Simulator
Crazy Taxi like;
Has the player sell ice cream in the area
|
|
|
|
|
|
|
|
|
|
|
3 - Pillow Fort Wars
Player has to take down the enemy's fort in angry birds style game
|
|
|
|
|
|
|
|
|
|
|
4 - Child with a stick
Rogue like 2D platformer
Player has quests by going into an area (like to save the princess)
can unlock different classes as the game progresses which can be changed at a main hub
|
|
|
|
|
|
|
|
|
|
|
In the end we decided to pursue the Sneak out of the house Idea.
Intro to C#
In this Introductory lecture to C# with Unity we made 2 scripts in C#.
The first script consisted of sending a message to the console, a message that could be altered in the Unity's inspector.
Talking String
For this we added an empty game object then created a script called "Talkingscript".
On this scrip we added a public string (i named mine message) then under Start method we created a function(?) that would make the the message display on the console at the start of the game.
we attached the scrip to the game Object, on the inspector wrote the message, I wrote "Hello World!"
Dice
The second script we made was to simulate a dice roll and getting the output on the UI.
Firstly we added "using UnityEngine.UI" so we could use UI variables in this code.
So we did two public integers, one for the minimum value and another for the maximum value, as well as public Text.
The integers we set them on the inspector while the diceText was dependant on the result of the random range given on the public void "OnDiceThrow".
This script was added to the canvas were we added a button and a text object.
Then set the button as interactable and OnClick dragged the canvas gameObject in and select to run the OnDiceThrow Function. Then we dragged the text object to the diceText on the diceScript component in the inspector.
Roll 2 dice + x sides dice
One of the tasks to do outside of lecture was to make a script to roll 2 dice.
Since I wanted to make it so that there is a choice between rolling just one or two I just added another button and another text for output for a second dice.
for the x sided dice I made yet another button and a 3rd OnDiceThrow function with a different script that uses the int diceSides to change the maximum value of the Random.Range, this int can be changed in the inspector after adding the function to a button.
Intro to Unity
Flappy Bird Clone
For the introductory lesson to Unity we were provided with some basic assets for a flappy bird game, make a basic working version of the game then adding an extra mechanic.
First thing was starting a 2D project on unity, once loaded adding a player game object.
On the player game object adding a spriteRenderer Component.
One of the assets provided was a sprite sheet with multiple images in a single image file. To get the singular images from the sprite sheet, I selected the image on the project window, then on the inspector selected the sprite mode to multiple then click on Sprite Editor to "cut" the desired sprites.
For a working prototype all that was needed was a bird sprite, a background, the ground and one set of pipes.
I added the bird sprite to the player game object as well as created more game objects in the scene to for the rest of the sprites.
Now having all the models needed, had to add the necessary components, collision for the pipes, ground and player object so they can actually collide as well as Rigidbody2D for the player object. Rigidbody emulates physics, so the player object can "fall" in this scene.
Now to make things start moving.
We wrote a Jump script in C# for the player game Object, this script grabs the RigidBody2D component and at the press of the mouse button applies a float value up (using a Vector2).
Then we wrote a C# script to make the pipes move, and a script to spawn them.
I then added a line to the jump script to make the scene restart once the player object collided with anything (pipes, ground).
With a Twist
For the unique mechanic I just added a projectile that would eliminate the pipes on collision.
So it wouldn't collide with the player object, on the layers settings I changed it so that the projectile layer ignores the player layer.
Since while playing you could continuously shoot projectiles essentially making it so that you would play the game without hitting any obstacles. I limited the shooting by adding a 2 second period of time where the player could not shot right after shooting the first projectile.
After I added a score system, I made it so that the player would get a point for entering a trigger box which is on the pipes prefab, right after the pipes.
I also added a highscore that is stored on the PlayerPrefs.
Since I included a play button to start the scene whenever the scene was being reloaded on collision the player would have to always click it to start playing again, since I found that annoying and after failed attempts of going around it I had the idea of "cloning" the scene and stripping it of the start button and such, so when the player dies for the first time they will be playing on the clone scene, on collision the scene freezes and after a delay reloads so the player can continuously keep playing without having to press any extra input or get the mouse if they choose to play with the spacebar button.
TRY IT HERE:
Player Controllers
On week 4 of this module we learned how to make Player Controller scripts by using Unity's Rigidbody component.
One of the scripts was a Top Down controller in which under Update method we set a Vector2 setting the move direction based on Unity's Vertical and Horizontal Axis input keys (WASD and Arrow keys).
Under FIxedUpdate method we set the speed based on rigidbody's velocity by multiplying the direction from the move direction by a moveSpeed float variable which we set as public in order to change the value in the inspector.
We also had to turn off the gravity scale otherwise the player gameObject would slowly fall down.
Course Activity Week
Cookie Clicker
Scene/gameview
For the week 8 of the module we started by doing a simple cookie clicker by just using the Canvas and giving functionality to buttons.
Initially we made a button that would give you a value per click then an upgrade button that would modify this value.
we also added 2 text (TMPro) gameObjects, one that would show the player score and another that would show the upgrade cost.
In scripting we used 3 integer variables, one that holds the player score, another for the value per click and an upgrade price.
Then we made 2 text variables.
We made the text variables get the TMP_Text component from the text gameObjects on the Awake Method while on the Update we scripted the score and upgrade score text to go into the text variables as a string.
With the variables set and the text set, we started making public void methods to be applied to the buttons.
The AddScore which added the score modifier value to the score upon being called (per button click)
in the BuyUpgrade method we scripted an if statement that if the player had an higher score than the upgrade price value that the upgrade value would be deducted from the score value, and it would call other 2 methods.
One to change the Upgrade price, doubling it, and the UpgradeButton where it would add + 1 to the score modifier value. Essentially adding 1 extra point gained per click.
The improvement task was to make an auto clicker button.
I made a button, like the upgrade button, it would deduct a value from the score, activate a RunAutoClicker method then the button would be destroyed in order to prevent multi clicking.
in the RunAutoClicker method I made it start a Coroutine method called AutoClick. this method gives a 1 second delay, adds a score then activates itself, this way making a loop. (probably not the best way to do it but it worked).
Scripts
RAD - Rapid Application Development
This week we were given 2 scripts and asked to do a 3D puzzle game using Rapid Application Methodology. We had until the end of the lecture.
We were all separated in groups of two, my partner for this game was Blossom.
We decided on making an obstacle course with traps and other elements that would affect the player gameObject on collision.
The objective of the game was to reach the end of the platform.
I decided to make the traps while Blossom focused on the level design.
I setup a Killzone that would destroy the player on contact and upon the player being destroyed the scene would reload.
I first made a spinning block (rotating on the Y axis in relation to itself) to try and kick the player out of the platform, but that didn't work out so well. However someone asked for a spring script to make a jumping platform so I utilized that code and modified so that I could change in the inspector, the x and z values were changed from 0 to a public float variable to allow this. I applied this to my spinning block which would send the player character out flying like intended.
I then applied the spring to static game object.
Then I set a trap that would drop balls on the player. I made a trigger box that would destroy the "gate" of the "container" holding the balls. since it takes a bit of time for them to drop i placed the trigger a bit before the player reaching the trap.
There was also a regular jumping platform that the player would need to get some mommentum to jump over the wall, on the other side a platform balanced on top of a capsule object was waiting then more spinning blocks.
I mostly coded the trap behaviours, made prefabs and then blossom placed them where she found best, I asked her specifically to exaggerate. Something to give the player a bit of a hard time.
Was scary having to make a "game" in just under 3 hours but ultimately I had a lot of fun.
Provided Scripts
KillZone
The Level
Spring platform
Falling Balls trap
Spinning block
Group Project
<My Family Turned Into Demons So Now I Need To Escape>
A.K.A
<Demon Escape>
Group Members:
Angela
Dominik
Shaun
This is a game built using Unity (version 2021.2.12f)
Under the theme childhood we first decided on a few things:
The purpose of the game is to escape the house;
Top Down POV;
2D.
As for the player experience, the objective of the game is to exit/escape the area, in order to do that the player has to open the exit door.
However the door is locked and "barricaded" so the player needs to find tools to unbarricade the door and leave the area.
The twist is that the protagonist's family members (who turned into demons) are roaming the area and will chase the player on sight to keep them from leaving.
Planning
Miro
We came up with a work flow plan dividing tasks by priority.
I have been using miro to help us organise our tasks and have set up a weekly team meeting to discuss the project as well as the direction we want to take the game towards.
I also have setup the project on GitHub so we can update the project as we go.
Later in week 5, me and Dominik reassessed the board and made weekly plan for divide work.
I organized a workflow and proposed colour coding each team member notes which would help visualise who is doing what and each other's work load.
Not everything goes according to plan but it definitely makes a difference having the tasks available like a quest board of sorts.
GitHub commits
Player Controller
I added the player controller based on one that we scripted in C# during a previous lecture when we did the Player Controllers.
The player can move in every direction on the Y and X axis.
Player can move using WASD and Arrow keys.
(Dominik later added the animator scripting for the player GameObject animations)
Camera
I also wrote the script to have the camera follow the player with the help of online documentation and online tutorials.
Enemy AI
I took upon myself to try to make the Enemy AI for this project.
I wanted a path finding system that would make the enemies follow the player so I searched for tutorials to do this, I came across A* Pathfinding Project that can be used for free.
A* provided a very helpful pathfinding grid that detects obstacles such as walls and calculates a path to a point while trying to follow the pathway and avoiding going through walls.
However the tutorial had the enemy follow the player across the map from the start and I wanted to make the enemy follow only after seeing the player.
I looked into giving the enemy a field of view and then initiate a chase from there so I managed to slap together something that does that even if somewhat limited.
Field of View, AI Chase
For the field of view, besides making it an area where the enemy will see the player, there is an obstuction layer that makes it so that if there is any GameObjects part of that layer in between the enemy and the player it will make it so that the enemy will stop "seeing" the player.
While seeing the player the Enemy would start a chase, when the player exited the line of sight, the enemy would stop seeing the player and stop chasing.
At this stage the Enemy AI was limited to being stopped in place waiting for the player to be in sight to initiate a chase.
It is scripted in a way that the Radius and angle view can be changed in Unity's inspector.
Peer Review 1
The first peer review went on a positive note. Based on what we had implemented some offered suggestions on what we could add to the game.
Some of those were to add functionality to the tools rather than just using them to unlock the exit.
Other was to add traps for the enemies, seeing as they would chase the player on sight.
A flashlight was also suggested, something to reduce the player's sight as well as an enormous map instead of various levels.
I have considered these features and discussed them with my group and ultimately decided by not implementing extras and focusing on the normal gameplay first.
Enemy Behaviour (route)
Given the nature of the game I wanted to have the enemy roam around the area in a random way. Thinking of a way to script this was a challenge in its own way.
I was limited by not knowing how to work with the A* pathfinding very well and was not sure if the roam was the most indicated behaviour for the enemy in terms of level difficulty. Dominik had previously suggested giving the enemy a scheduled route.
Then I had an idea, in the previous version of the AI behaviour the enemy would chase the player as soon as the player started the game by getting a reference to its transform position.
My idea was to take advantage of that and instead of having the enemy follow the transform of a player, to have an empty GameObject teleporting between set points randomly for.
This way there was as bit of a pattern to the enemy as a route would suggest as well as a randomisation as to which place in the area the enemy would go to.
Instead of using my previous AI path script, I used A*'s AIPath, Seeker, AIDestinationSetter Scripts which take advantage of the pathway grid and offer some customisation options.
Then I made the teleporting GameObject, and wrote a script to handle the teleporting as well as a coroutine that triggers the teleport every x seconds.
The teleport points are set by Vector3 coordinates which can be changed in the Inspector, the time between teleports can also be changed in the inspector.
Initially I had thought about using empty objects to gather the transform positions as teleport points but the way I was writing the code did not accept that information so with the help of the Assad (our lecturer) we managed to make it so it would take Vector3 coordinates directly from the inspector.
Issues
At the time it had not occurred to me, has I had an enemy with a decent field of view but this field of view was dependent on the rotation of the gameObject, this entered in conflict with the way the enemies would be animated. When Dominik tried to implement the animation it was rotating.
We tried using rigidbody to freeze rotations but it would
a) conflict with the way the enemy moved
b) the field of view would be frozen stuck turned up
While I was thinking about this, it occurred to me about how children objects function in relation to a parent object, not really thinking about it I set the enemy graphics object as the parent to the behaviour gameObject, needless to say that it didn't work, the GFX was in place while the behaviour was going on about its day. However this gave me an idea, there is an object in the scene that is following another object which moves around freely. The camera following the player, this gave me the idea of making the enemy GFX follow the behaviour transform position.
I had an enemy GFX script from a tutorial that worked when flipping the sprite so I passed information on that onto my group colleague doing the animations so that it would help him implementing them.
Health System
For the health system I wanted hearts rather than a health bar and have the player get returned to the beginning while retaining the items they had picked up.
For this I set the player to have 3 lives and set an empty game object as the "startPosition".
On collision with the enemy it checks if the player has 1 or more lives then ports the player to the transform position of the object, then on the update method when the player has less than 1 life it loads the game over scene (the destroy line I realise it is unnecessary now)
To make the lives reflect on the UI I made a script where we can drag the lives images gameObjects into it on the inspector, gets the lives script from the player game object on the start method. On the start method I am also setting which of the images is active.
I then used a switch statement which checks for the current lives the player has and setting which lives display to show based on which is the case.
(Some) Menus, Level Select
Shaun had made us a main menu with a start and quit Button, he also had made a pause menu.
In terms of menus I only added some buttons and scenes I found necessary. I added an end of level scene, a game over scene, credits scene and edited the main menu to include a button for the credits scene as well as a button for a level select scene (later I scraped the level select SCENE because when implementing sound I wanted the same main menu track to keep playing while on the menu).
On the main menu I added a separate canvas game object where I would add my levels buttons, this canvas would start inactive and then when pressing the level select button it would activate itself and set the main menu canvas inactive.
As for selecting the level I did not want the player to be able to access all the levels without completing at least the previous level.
I set up a Level Manager, in all the different end of level scenes I set that it would set an int to the player preferences of level complete = 1. then on the start method of the main menu it would check if this integer was 1 or NOT 1. In this case, if it was 1 then it would show the button that triggers the specific level to load.
Sound
For the sounds, I made a list of sounds that I needed and looked on Pixabay for sound effects as well as tracks to use on the menus and background during gameplay.
As Pixabay offers royalty free tracks it seemed like a good source for audio that I could use.
I tried to add audio to the mixer and set separate mixers, unfortunately I did not have much make it so my trigger would activate the sound as it was imported in the inspector.
I had made this OnTriggerEnter2D to trigger a sound if overlapped by an object with the player tag with the player tag. I did not have the time to learn it so that the audio would go though the mixer so the sounds were playing at default level of noise of the clip.
EnemyRandomSound was adapted from a script from somewhere on the unity forums that would allow the player to select a quantity of audios from an array and play them in a random range that could be set on the inspector. (unfortunately I forgot to save the link)
I used this script to make the demons make a type of grunt, could have added different sounds but I was pretty happy with the few that I had.
I also looked a bit at the audio settings present in the audio source and checked the spacial sound, made a few changes to my liking about how the player hears the demon grunts in particular.
The template I used it various things. like when picking an item and when using it. it was playing directly after pickup/trigger box or when using an item.
Enemy random range interval to play sound
Basement Puzzle
I also duplicated the door script form Dominik's inventory system so I could modify it as needed and on the basement level i made 2 different ways to make the puzzle, the one that we settled on was on trigger to destroy a floor tile which would expose a candle AND destroy a floor piece with a collision box that would be covering a pentagram, upon "placing" all the candles it would reveal a pentagram (or somesimilar concept) which would then drag the player into "hell"/"catacombs".
short opinon
Overall was a good project, a shame I was out of time to properly debugg the mechanics and puzzles but I made sure the player could finish the first 3 areas (including tutorial) before submission.
I was sad that we did not manage to implement all the sprites and animations for this project.
It was also a challenge for me to work with one very irresponsive teammate while having another that would work really hard, for group project this felt very unfair.
But in the end it was a good learning experience, I am fairly happy that the prototype game can be played for more than 1 minute!
Resources
Miro
Unity
A* Pathfinding Project
https://arongranberg.com/astar/
GitHub
Music/Sound Effects source
Youtube tutorials:
2D PATHFINDING - Enemy AI in Unity
2D Field of View [Unity Tutorial]