Introduction
Okay so now I have a better grip of the basics I want to try to make something that isn’t just a copy and paste of a well known game, also adding on furthering these mechanics to push them further. Such as instead of just moving left and right, how about moving in all directions? Or adding an effect to enemies or different types of those enemies instead of just one.
This is why I settled on doing a top down shooter as it felt as a good next step, especially for what I had learned so far and what I had planned for it. Basically I had a running joke about squirrels with guns with some friends from a game we saw where, well a squirrel has a gun, it is just one of those things that is so silly it is brilliant, and so I want to make that into the game I am making here. You can see this develop as well more through the art as I don’t start by making the sprites for the game, but with making sprites more just about it, then deciding on top down later on
I decided to make it make sense to base it off the squirrels’ fight in Britain of red vs gray as the gray invasive squirrels are killing off the red squirrels which are the original ones for Britain. And so the main character will be a red squirrel fighting back the gray squirrels from their land, with a gun because I can. However the gray will have swords and not guns, one because I am not sure how to make a enemy shoot a gun and two I feel like it would track the player too well and just instantly kill them, so we are going to stick with swords
Game Link
Just in case you want to see what this is all about:
Required
Movement
Much like the space invaders we need to be able to move, and I want to be able to move in all directions this time, this technically is a requirement, but is nice and I want to work on movement more in general really anyways. To do this I just need to take 4 inputs for wasd (w up, a left, s down and d right), this then lets them move in all these directions and the inbetweens as well by pressing two at once to get the middle. To do this we just need to make a movement script and put it on our player so it moves them and not like the background or something, the script I used for this is:
As you can see it uses the input system of Unity by getting their inputs from axis raw and calling the horizontal and vertical of these, allowing us to apply these to the player’s movement. Putting raw on the end allows us to get the input as just a straight one which helps as inputs from keys can be different and so taking it as raw allows them all to be one and allows us to completely control the speed and make them the same in every direction.
Lastly we have a clamp which is making sure the player cannot move outside the camera as it is supposed to be fixed on that so if you can just leaves it kind of breaks it, so we take the boundaries of the camera and use a clamp which basically says “you can move everywhere but beyond here”, so if we put two on each side we can just keep them in.
Turning
Okay so next we want the player to be able to turn as otherwise they can only really shoot upwards which doesn’t help anyone, to do this we also need to make them face at something the player can control. For this I am going to use the mouse and just make it into a crosshair, I will split these up though just so it is easier to follow for the both of us.
Crosshair
Okay so firstly let’s make the object they are going to look at as then we can actually test if they are turning or not when we come to that, plus because this is definitely the easiest of the two, so let’s get it out the way first.
To do this we just need a simple script which we put on the object that will be tracking the mouse, then we can make it follow and just hide the mouse, we do that with this:
This works by first hiding the mouse so we can replace it and then for every frame it looks for the mouse position, once it is found it then sets the crosshair’s location to that position, mimicking the mouse’s movements, which then just leaves the turning for this left.
Turning
Now we have a crosshair to look at, how do we make the player actually look at it? Well for this we need to change the angle, not the position. Which is changed like position but kind of different, we then take this change from the position according to the crosshair, so if its under it it will look down, basically making it follow the crosshair angle wise, which I do with this:
As we are just moving it to face the mouse we take where the mouse is as a vector3 which basically stores 3 values like an array but is mostly used for the coordinates of objects and their manipulation. Then we make a float (not whole number, so it can have decimals) called angle where we use Mathf.Atan2 to combine the mouse direction y and x to get its direction. Lastly I’m not going to take credit for this but it’s basically you take 90 or add 90 or 180 until the character faces the right way, it will track but not face seemingly for no reason, so the credit goes to my teacher Adrian for helping me for this bazare error. Then for the last line we are just applying this to the player through all of this
Shooting
Okay so now that the player can turn and face where the player wants we need to be able to actually shoot at the enemies, so we need to make our bullets, for this we need to spawn them and make them kill enemies. However, to shoot we need to spawn them and then have them move forward on creation each time, which I will be separating as the moving will trigger from the bullet and the spawning will trigger from the player.
Spawning
Okay so to spawn the bullets in we take the current bullet as prefab (take it from the hierarchy and drag it into the assets) which we can then put the script on, this can then be spawned and have the set scripts and such on it, allowing is to also delete them after being destroyed and just making another one to make it easier. So to do this we just use this:
Okay so this one is very simple, we check for if the player has clicked the mouse, if so we activate generateBullet, this then checks where the mouse is and spaws the bullet from the player facing at the mouse, allowing for us to get the effect of it looking like it actually came from the gun and still following where the player wants it shot
Then you just drag that onto the player and then drag the bullet prefab in the gameObject so it can spawn that when the player shoots
Movement
Okay so now we need the bullets to move so we need a script for that, it is quite simple, we just make them go forward pretty much, through this:
Okay that might have been a simplistic view on it, as it also detects if it hits an enemy and activates a routine for that you can see on the enemies later, also destroying the bullet for obvious reasons as it was used and then should be gone. For the direction we just take where the mouse was again and make it move in that direction, however it only takes this once shot so don’t worry, it won’t just track the mouse, though that is kind of a good idea I could use in the future.
Enemies
Okay so for enemies it is a bit harder, we want them to follow the player, interact with the player and bullets and give score on death, so we need 3, the score is the easiest so lets do that
Score
Okay so firstly let’s make them give score when killed, for this we need two scripts and to make the enemies prefabs like the bullets, and a text for the score to go in. So first let’s make the script for the text so we can see the score change once we kill them, for this we use:
Okay so basically this gets the current score and for each enemy they will add to this, later on, basically when they die their score value gets set and scoring is called, which then adds the score to currentScore and displays it.
Next let’s set up the collisions so we can see where this is in the script
Collision
Okay so the collision script has the other half of the score script in it and let’s use collide and actually die when the enemies hit us, so let’s sort it out, I allowed this to happen through using this:
Okay so the boom is later on I basically added a blood explosion to the enemies once killed that looks like this:
I’m not sure how to put videos in so I just copied the link to where it is in my google drive which should hopefully work.
Anyways, after this we have two checks, one for a tag “Bullet” and one for a tag “Player” these have the outcomes we want for both, so for the bullet it gets destroyed and gives the scoreKeeper script its score value and plays the routine like mentioned before. However for the player it also deletes itself but stops the spawning, kills the player and starts a reset routine which we will cover later on, basically if you lose your cna restart again without booting up the game again, it is pretty simple.
Score
Okay so now we need the enemies to actually hold this score and so we need a script which is very simple for this, being this:
No I am not kidding, we literally just need them to have a score attached to them the score routine can take, which we can change for both the enemies, so the basics have 20 when the armored have 50 since they are harder.
Movement
Okay so now let’s finally make the enemies actually follow us, this at first might seem very hard and it would be expect for the fact that Unity knows it is and so basically has a command that just makes one object follow another, so since it is literally made for this you can imagine it is pretty easy to do in practice:
Okay so it gets the rigidbody of the enemy (a component you basically put on any object you want to collide and interact with each other, for example without it the enemy would just go through the player, and not even have the function to follow as it is part of this shortcut sadly), then we set a gameobject as the target (which will obviously be the player (just drag it from the hierarchy onto the enemy in this scripts slot once this is done))we also have a check to find the gameobject player which in this game is just called Squirrel which yes I know is kind of confusing but the rest are gray and armored so it technically works.
If this returns a false then the game won’ crash and the enemies just stop, such as if the player dies, basically being a nice quality of life for the player which we will touch upon later as well. Much like before we get the enemies position as a vector 2 (we only need the x and y) and set this as MoveTowards (this is the shortcut I mentioned before), putting in the enemies’ position and the target’s position, along with a speed timed by fixedDeltaTime (which basically fixes the time so that even if your playing on a microwave or a supercomputer, the game runs exactly the same, time wise anyways). This basically just takes the enemies transform as the host and the target as the target, using this speed variable so we can limit how fast they chase which will come in later. Next we figure out the targets’ angle so we know where to go and use the same calculation to make sure it is the correct angle from the gun aim script, which we can set to the enemy’s rigidbody so it constantly is looking at the player, just so they look atleast a little less dumb.
Different Types
For this I wanted to dabble in adding a different enemy as well, but what would it be? Well it’s basically a crusade against the red squirrels so why not an armored squirrel? I would have given them more health but I’m not sure how to do that, and so I made them faster to act more like charging knights like what a lance knight would do. This is done through the speed state which is higher on the armored, that is it, then we take both of them as prefabs (drag them from the hierarchy into the files) so we can use them later so we can delete them as they are killed but make more with the prefabs, such as for spawning our endless wave on our player of course.
These are their inspectors, as you can see, the only difference is the scores and speed as I said
Spawning
This is a big header basically because it is the most important and longest script by a long shot, even going across two whole screenshots. However it is so big as it spawns them randomly on every part of the outside of the screen, slowly spawning faster and even slowly spawning the armored squirrels as it goes on. This is very complicated but that is in basic terms which it all does, so here it is:
Okay so firstly it sets an instance which basically lets us call upon it every time the scene is set which will be relevant later, basically every time it is called it is reset. Then next we set the timer (controls how fast the enemies spawn and if the armored spawn) to 2 so it ramps but still gives a good amount of time for the player to get used to the gameplay first so they aren’t just immediately killed. Then we set a coroutine which basically calls a routine inside of the code once the current routine is finished, finally we set keepSpawning to true so that the routine knows that it should start spawning enemies.
After that we have the IEnumerator which is basically fancy for “hey here is that subroutine you asked for”, for every coroutine we have a IEnumerator, you cannot have one without the other as one is the activation for the other, so without the coroutine the IEnumerator wouldn’t have a trigger. In this we make it wait a second, just to let the player have at least, well a second to gather their bearings before the crusade starts, the we have a while which basically activates the routine while keep spawning is true, just so when it isn’t (the player dies) we don’t keep spawning as it is unneeded. Then we have 4 cases, these are basically ifs but different, basically it takes the spawnLocation and chooses one of the cases at random, which then randomly set the spawn location in one of the four sides, allowing enemies to spawn in a completely new side and part of that side each time.
Then we set this spawn position as a vector2 so we can apply it to the enemy later, then we summon this enemy by using Instantiate which basically acts as a array and when it is used, looks for a given object in a given instance, which you can then apply stuff to, such as their location and angle which we do. Then to have the spawning split up we wait for the time in the timer, this is so we can speed up the spawning later on as the game ramps up. Then we add to the numberOfEnemies as, well we just spawned a new one so obviously one is there, lastly we have two if statements, the first checks if the numberOfEnemies is more than 5 but less than 11, if so it sets the enemy type randomly between the two types (armored and not), the same for the else if which checks if there are more than 10, doing the same, basically if there are more than 10 than armored should probably be spawning, so we use this to make sure it keeps swapping. Then the other checks if the timer is more than 0.5, if so it takes 0.02 off it, this makes sure it never gets faster than 0.5 but slowly gets faster per run, doing this ramping I keep talking about.
Menu
Okay and lastly what I have been referencing throughout this is the usage of scenes, because I got introduced to them by my teacher Adrian I thought I could use them to not only make a menu and game that are seperate, but if the game scene is set, I can call it to restart the game, without the player having to do it themselves. Which then evolved into the player being able to die, go into the reset screen and just restart, which I’ll explain here
Menu
Okay so first is the menu, so I wanted to use those first sprites and thought a menu would be perfect for this, so I just slapped one together, put a button covering the screen and when it is clicked this script plays:
Which yep literally just loads scene one, which is the game scene, just starting the game up, is as simple as that
Restarting
However restarting is a whole new thing, we have to know when the player has died and trigger a restart from that, preferably after telling the player they can and letting them do it so they are ready, leading to me making this version of the start script:
Okay so this sets the restart button up which like the menu button covers the screen, just it is toggled by default so it only appears and can be triggered when the player is dead. However to help with quality of life first we check if the player ever touches the escape key, if so the application should close, this is just so the player doesn’t have to manually close the game themselves. Then we have the restart game IEnumerator which if you remember is activated from enemy collision, so when the enemy hits the player, wait 3 seconds and turn the restart button on. Lastly we make a restart script we attach to the restart button that again loads the game scene, loading it when pressed.
Conclusion
This is by far the best game I have made and it is definitely the most complicated too, however despite that I also had the most fun with it because of how far it pushed me, I am looking forward to use what I learned from this in the future and definitely want to come back to this prototype in future if any of them