You are on page 1of 9

Game for shooting enemies

1. Import FPS. Go to Assets - import package – characters. Import Unity Package. Enable
anything – import Assets folder now contains Standard Assets. In here we have
characters. In here First Person Characters. Add a plane object to avoid the player fall.
Go to hierarchy - right click – create 3d object, add a cube. Rename as floor - center the
position 0 0 0. Scale x = 20 y = 0.1 z = 20. Create a folder Game. Inside this create a
folder Materials. Inside this create a material for the plane. Place the FPS character
Prefab in the scene. Drag the FPSController in the hierarchy. It contains audio and
camera. Delete main camera. Save the scene and drag and drop it to the Scenes folder.
2. Create a GameController. In hierarchy create a new empty object and rename as
GameController. Put it in the position 0 0 0. Select the directional light, floor and FPS
and drag and drop to the GameController. Rename FPSController as Player.
3. Add a gun. In hierarchy, inside of FPS, add an empty object and rename it as Gun. Add a
cube inside de Gun. Remove box collider from this cube. Change the cube scales and
position. Add a second cube and do similar actions to form an L as a Gun. Select the
cubes - Mesh renderer - cast shadows – off. Assign it a material.
4. Make a Script for the Player and the Bullet. Don't change the FPS script because is only
for the movement and physics. Create a folder Scripts inside the project folder. Inside it
create a Player script and Bullet script. Add the Player script as a component of the
Player in the inspector. In the hierarchy, select Player, drag and drop the Player script
on the Player. Open the Player script. Here we have the update method which is called
on every frame. So GetMouseButton return true every moment the mouse is held
down. This is use for machine guns so you can shoot several bullets. For pistol use
GetMouseButtonDown so you shoot one bullet for every time you press the trigger. (1)
5. Instantiate a Bullet and take it off. In the GameController object create an empty
object called Bullet. Inside this create an empty object called Container (an
intermediate object to separate the logic part from the visual part). Right click – create
3d object – Sphere. Remove the sphere collider. Rescaled the sphere reducing it. Create
a material for it. Change its color. Drag the Bullet script in the Bullet object. Add
component - sphere collider. Change its radius to reduce size. Mark Is Trigger box to
use the Bullet for trigger overlaps. The Bullets are going through Enemies and hurt it or
kill it. Create a Prefabs folder into Game folder. Select the Bullet and drag and drop to
the Prefabs folder. Delete the Bullet from hierarchy because it is already saved. Open
the Player script. Here add public GameObject bulletPrefab (2). In Unity, select Player
in hierarchy. Drag and drop prefab Bullet in Bullet Prefab field on Player inspector. Drag
and drop the Player into the Prefab folder. To instantiate the bullets (3) we need to
consider the bullets position at a certain position and in front of camera of Player and
the Player itself. In the Player Script add a reference of the Player Camera (4). In Unity,
drag and drop the Camera in the Player Camera field – apply. We have to make these
Bullets forward. Go to the Player script and add the direction for Bullets. We want to
move the Bullet forward. We set the forward vector of Bullet to be same forward
vector as the Player Camera. It is going to point to whitherever the camera is looking at
(6). Go to the Bullet scripts and make a logic for the bullets movement. Here we define
a float speed (7). In the update method we are going the bullet move (8).
6. Make an Object Pooling Manager. The bullets exit forever, expending memory. We are
going to add a lifeDuration to the Bullet script, so every time we add a Bullet, it is going
to take some time (9). We also need a lifeTimer that is going to be an internal clock for
the Bullet that is going to countdown and when it is going to 0, we get rid of the Bullet
(10). In the Start method, we make lifeTimer = lifeDuration; (11). In the update method
we decrease the Time.delaTime (12) until it gets 0. If this happens, the Bullet should be
destroyed (13). It is going to work as time passes. Every time we add a bullet to this
game (instantiation process) it take some time for Unity to get that element to put it
inside the game an d make it work. Creating and deleting elements are expensive
operations. To avoid that, we need a pooling manager for holding objects. That hold a
Bullet and preload a certain number of them. We make these objects inactive and
hidden in the game. Every time we spawn a Bullet, instead of instantiating you are going
to get a Bullet from the pull of objects because we already have one Bullet available, it
is going to be activated. This process is known as object pooling and save you lots of
processing power and memory. Create an empty object and put it outside of the
GameController. Rename as ObjectPoolingManager. Position it at 0 0 0. Make a script
for it and call it ObjectPoolingManager. Organized the scripts - create a Game folder
inside Scripts folder. Drag and drop the Player and the Bullet scripts inside Game folder.
Create Util folder insider Scripts folder. Put the ObjectPoolingManager script inside Util
folder We are going to put a reference, so drag and drop ObjectPoolingManager script
on ObjectPoolingManager. At the ObjectPoolingManager script ther is going to be a
reference to the instance of the ObjectPoolingManager (14). Now, we make a pattern
for defining a property (15). But now is going to return null. In ObjectPoolingManager
script instead of using Start method we can use Awake method (16). We get rid of the
update method and use a new GetBullet method (17). In the Player script, at the
update method, inside if loop, we type ObjectPoolingManager.instance.GetBullet(); so
the player could get access the instance in ObjectPoolingManager script without having
a direct reference to it (18). In the Player script Instead of instantiating a Bullet, we are
going to get a Bullet from the ObjectPoolingManager. We are going to make a mix of
the singleton pattern. The ObjectPoolingManager is going to have a reference to the
only instance of that pooling manager available in the scene. We want the
ObjectPoolingManager to be able to access the Bullet prefab. In
ObjectPoolingManager type public GameObject bulletPrefab; (19). In Unity, select the
ObjectPoolingManager in hierarchy, drag and drop the Bullet prefab in the Bullet
Prefab field of ObjectPoolingManager script. We want to preload a certain number of
bullets. In the ObjectPoolingManager script we type public int bulletAmount = 20; (20).
In the Awake method, we are going to instantiate 20 bullets (21). We execute a loop 20
times (22). We store the reference for the Bullet (23). We pass transform as a
parameter because it is going to reference the ObjectPoolingManager (24). The 20
bullets are going to be disable (25). In Unity, drag and drop the Bullet prefab in the
Bullet Prefab field in the ObjectPoolingManager script in the inspector. For GetBullet
method, we need to define a List of bullets (26) and in the Awake method, before we
instantiate the bullets, we are going to preload a generic List of bullets and including its
capacity or bullet amount, 20 in this case (27) so we already pre allocate that amount of
spaces in our memory to load bullets. We have to store the references of the bullets
before we try to use the GetBullet (28). We are going to set the groundwork for making
the object pooling to work. We need to go to the ObjectPoolingManager then we have
to make the GetBullet method work. So we want to iterate. So we want to iterate over
all of the prefab instances that we have loaded and we need to check if any of them are
inactive and if it is, that’s the bullet that we are going to use (29). But maybe all of the
bullets are being use so we are going to iterate over all of them not only to be available
because they are all already in the scene. It means we should instantiate another bullet
so we grab the code of the for loop for making a new prefab bullet (30). Here, delete
the line prefabInstance.SetActive(false); because is no need to use it (31). We set its
parent to be the ObjectPoolingManager (32) and stored it in the bullet list (33) and
return the bullet added (34). In the Player script, instead of using the instantiate
method call in update method, we get the bullet from the ObjectPoolingManager. We
will copy line ObjectPoolingManager.Instance.GetBullet(); and pasted instead of
Instantiate (bulletPRefab); (35). With this change, the bullet is spawned by using
ObjectPoolingManager. Remove the reference for the bullet Prefab because the Player
no longer doesn’t need to know what is the exact prefab (36). In Bullet script, instead of
calling Destroy(gameObject); (37) or instead of removing the bullet from the game.
However, the lifeTimer is set it in the Start method which is only called when the object
is instantiated, but since this is going to be pulled, we need change this Start to
OnEnable (38). Every time we click the duration is set back to its original state into the
lifeTime. If we set Bullet Amount to 2 in the inspector of the ObjectPoolingManager
and if we click bullet 1 is instantiated, if we click twice, both of them are active. We are
reusing bullets retreating them from the ObjectPoolingManager and no longer we
instantiate them. If we click several times very quickly, new bullets are added to the
ObjectPoolingManager and it is going to use all the bullets available but they are going
to be reused. No more memory allocation, no more a very large amount of processing
involved into adding these bullets. The game is going to be very efficient.
7. We want the player to have a limited amount of ammunition. Open the Player script.
We put a public int initialAmmo = 12; (39). We put a private variable that is store the
ammo (40). In Start method we do ammo = initialAmmo; (41). In the Update method,
before we spawn any bullets, we have to check if we have enough ammo (42) after
pressing the mouse button for the Player to shoot. So, ammo--; decrease one the
amount of ammo and store it in that variable (43).
8. Organize, group variables to read them in the editor. We are going to use an attribute
in the Player script. We give a name for the label “Visuals” that is going to appear in the
editor (43). Do the same with label “Gameplay” (44). In Unity, you can see in the
initialAmmo variable once the game starts, it is set to 12 and as we click ammo is
decreasing until 0. And if we try to click again, we are run out of ammo.
9. User Interface. We should show how many bullets the Player has, so we need to make a
User Interface, an area to give information to the Player. Go to the hierarchy, right
click, choose UI – Canvas, which is an area to put different User Interface: text, buttons,
group of buttons, panels. Doble click on Canvas -- choose UI and then text. There is a
separate camera that is rendering this staff. Select resizing tool, click the text and move
it to the top left. You can increase it size. Choose the color and font style. In the
inspector, add text Ammo:0. Increase the font size. To make that value to read for the
Player, make a script to control our canvas. We will do this in the GameController
script.
10.GameController script. It is going to control several aspects of the game: how long
Player is alive, check if the Player is dead and send the message if he died, count the
ammo. Go to Scripts folder -- Game folder -- create GameController script. Drag the
GameController script in the GameController. Having GameController selected, doble
click the GameController script. This object has to be selected. Open the
GameController script. We indicate where the Player is, so type public Player player;
(45). In Unity, drag and drop the Player in the variable Player of the GameController
script in the inspector. We add a header “Game” (46).
11.Ammo system. In Unity, drag the Text in the ammoText. In Player script to access to the
variable ammo make a property. We give the Player some chance to recover ammo.
We make a box we can collect. Create an empty object in the GameController and call it
ammocrate. inside this create an empty object and rename it Container. Inside this
create an object and rename it Cube. Remove its box collider. Rescale it, give it a
material and color. In the Game folder create a script named ammocrate. In hierarchy
-- ammocrate drag and drop ammocrate script. In hierarchy drag the container and
drop in the container script. Add component box collider to the ammocrate. Change
the size of box collider. Add component rigid body to apply the physic to the
ammocrate. Add a particle system in the ammocrate. We want that if the player
collides with the ammocrate then collect it. We have trigger collisions and physics
collisions. Go to the Player script. In the ammocrate script, back to the Player script,
open the Prefabs folder and drag and drop the ammocrate inside it.
12.Health system. In the Player script like the ammo we can have the health points. Add
text to canvas with Health: 0. In GameController we need to put a reference to the
health text. Drag the text health and drop in the GameController inspector.
13.Create an enemy. In the GameController create empty object. Rename it to Spike.
Create an empty inside Spike and rename it Container. Create a Cube inside Container.
Remove the box collider from this Cube. The Spike need to have a collider around it. In
Script folder in Game folder create script and rename it as Enemy. In Enemy script drag
the Enemy and drop it in Spike. Drag and drop the Spike in the Prefab folder and delete
it from hierarchy.
14.System for Knockback Effect. When Player collides with Enemy, he is going to receive a
force to make him propel backguards. In the Player script implement a knockback
effect. Create a script called ForceReceiver. Open it. The ForceReceiver script can only
added in CharacterController. Our Player contains CharacterController that came from
our FPS package. We have the Player script and the ForceReceiver script. Go to Player
script. In the inspector select Player and press apply.
15.Shooting Logic. Create an empty object in the GameController. rename it to
ShootingEnemy. Make a Container object inside it. Inside this Container create a
capsule object. Remove the capsule collider. Apply a material and color. Make a script
for that ShootingEnemy. In Scripts folder in Game folder, open the ShootingEnemy
script. Change the extend monobehavior por extend Enemy because that is an enemy
as well. We want the ShootingEnemy to shoot bullets to the Player. ShootingEnemy
needs reference for the Bullets. It also needs to have a reference where the Player is, so
Enemies can shoot at the Player. Drag and drop the ShootingEnemy script in
ShootingEnemy inspector. Back to the ShootingEnemy script, the reference to the
Bullet prefabs is in our pooling manager which is in Scripts folder -- Util folder. Open
ObjectPoolingManager to fetch (buscar) a Bullet. In ShootingEnemy script we need a
logic for getting the Player and for making a Bullet and for shooting at the Player. We
are going to get the reference of the Player and for the Player script. We make a logic
for ShootingEnemies to shoot at a Player. We have to make a Bullet. Grab (utilice) the
logic we did for the Player: spawn the Bullet object, set its position and set its forward
vector in the ShootingEnemy script.
16.Shooting distance. We are going to make a logic for make sure the ShootingEnemies
are not going to perform the shooting if they are not close enough to the player (at a
shooting distance). For now, Player is not hit by the Bullet, the bullets are not
destroying Enemies and the Enemies are not destroying the Player. We need a logic in
the Bullet that let us know its origin. If the Player shoots a Bullet we don’t want that
Bullet to hurt a Player. If the Enemy shoots a Bullet we don’t that Bullet to hurt an
Enemy. In the Bullet, whenever a Player spawns a Bullet we need to tell it that Bullet is
going to be spawned by the Player. Go to the ShootingEnemy script. Whenever we get a
reference to the Bullet in the Player script, we have two things that can hurt the Player:
The Enemy and the Bullet. Go to the Bullet script. Go to Player script. In Unity, in the
ShootingEnemy -- add component -- capsule collider. Adjust the height to 2. Now when
we collide with Enemy decreases our health. Select Player in hierarchy, the Player has a
capsule collider. We need other collider for trigger collisions. Add component -- box
collider. Change the y and mark is trigger. Go to Player script. Change
onControllerColliderHit for OnTriggerEnter. Change ControllerColliderHit Collision for
Collider otherCollider and hit.collider for otherCollider. Go to Unity, apply changes in
Player.
17.Logic for colliding the enemy. ShootingEnemy contains a capsule collider. Is Trigger is
marked as false. The Bullet prefab contains a sphere collider. is Trigger is marked as
true. The collision between the Bullet and Enemy doesn't happen because at least one
of these elements need to have a Rigid Body. We do that in the ShootingEnemy, select
it -- add component – RigidBody. Go to Scripts folder -- Game folder -- open the Enemy
script. Do a logic similar to the Player. Back to Enemy.
18.Enemy walks towards the Player. There are AI built-in mechanisms to make it easy
work with navigation and navmesh (navigation match). We need to tell Unity what is
the area our Enemy is going to be able to walk around. We want the Enemy to walk on
the floor. We need to enable the floor as a navigation area. Go to Unity -- window –
navigation - object -- check navigation static - bake -- radius and height of the agent.
Agents are the elements that navigate around here in this case Enemies. We can define
the angle for going over slopes, bake precompile to regenerate information our Enemy
is going to be using for the navigation. We need to tell Unity that our Enemy is going to
be a navigational agent. Select ShootingEnemy -- add component -- add the nav mesh
agent. Adjust the base offset. We need to tell through the script where the Enemy has
to move to. We are going to make it move around towards the Player. Then we need to
go to ShootingEnemy script. Store a reference for navmesh. You can put some distance
between the Enemy. The Enemy stopped because we are far away from it. If we move
close enough it is going to shoot and move toward the Player. Update method
destination is only set if the Enemy shoots. If it doesn't then it is not going towards us.
So make another distance in ShootingEnemy script. Chasing distance is only set if the
agent is within that chase distance. We need another timer.
19.Make sure we are not going to lose the ShootingEnemy. Drag and drop the Enemy as a
prefab. Whenever we kill Enemy (health = 0) we want the ShootingEnemy to fall to the
ground. In the Enemy script, logic for calling OnKill method if health is less or equal than
0. In ShootingEnemy script, we want to Enemy fall down once be killed. Add more
Enemies. in GameController -- create an empty object -- rename it as EnemyContainer.
Drag the shooting Enemy inside the EnemyContainer. Right click -- duplicate several
times. We need to make a logic when we kill all the Enemies so we beat the level. In the
GameController -- canvas -- 2d. We need a reference to the EnemyContainer. We need
to count how many Enemies we have. In the GameController script, go to Unity in the
canvas create the Enemy text. Go to the GameController. Drag the Enemy text and
drop it in the inspector. Select EnemyContainer and drag and drop in the inspector. We
need to update Enemies. Go to Enemy script. Back to the GameController to count and
see how many Enemies were killed. We need to check if we have 0 alive Enemies. That
means we finish the level. Write a logic for showing a you win message. Add a text in
canvas position 0 on x and 0 on y. Increased its side. In the GameController we need a
reference to that infoText. I am going to open the GameController script. In the
beginning of the game, we need to hide the infoText. Drag the infoText in the infoText
inspector.
20.Logic for when the Player dies. To make the Player loose we need to increase the
damage that the bullets are giving. Select the Bullet prefab. Increase damage to 20. In
the GameController script check if the Player has been killed. In the Enemy script we
want to make the Enemy stop moving or stop shooting. If they notice that the Player
has been destroyed. Go to the GameController -- select the Enemy Container. Choose
one of the Enemies. Once they fall we could disable RigidBody. If stops we don't want
phisycs to be applied anymore. If we kill and Enemy and it falls to the ground. If we walk
on top of it we are still being hurt and we don't want it. Whenever we get hurt by the
Enemy we can check if they are killed. Similar check for the Bullet. Go to Player script. If
an Enemy has been killed it not longer can hurt the Player. If the Player is destroyed in
ShootingEnemy script. We need to define where we check if the Player has been killed.
Once the Player is killed we don't want to be able to shoot Bullets because we are dead,
and we don't won't be able to move. If we disable the CharacterController I can't move.
If we take off the First-Person Controller we stop looking around. Go to Player script
and go over the logic where we shoot Bullets.
21.Make a Menu. File -- new scene -- file -- save scene. Name it as Menu. Move this file
Menu to Scenes folder. In the Menu hierarchy add canvas. Choose 2d -- add a text.
Rename this as FPS text. Select camera and change the color if you want. In canvas --
add a button. Change the text to play. If we click to the play button we should go to the
Level1 scene. On Scripts folder -- create a Menu folder. Inside Menu folder create a
MenuController script. In the hierarchy create an empty object and position in 0 0 0.
Rename it as menu controller. Put the main camara and directional light inside de menu
controller. Drag and drop the MenuController script inside the MenuController
inspector. Enter in the MenuController script. Go to Unity -- select the button in the
canvas. In the inspector there is an On CLick() section. Here we can add different
callbacks or methods. That can be call when that button is click. Click on the plus sign.
Drag and drop the MenuController here. Select the callback -- MenuController –
OnPlay. Files - build settings -- add open scenes -- add Menu scene. Save go to Level1.
And do the same. Window -- lighting -- scanned -- disable auto – build. If we win or if
we lose the game we back to the Menu. Go to the GameController -- add scene
manager namespace.
22.Create a HealthCrate. Duplicate ammocrate in the Prefabs folder ctrl + d. Rename
healthcrate. Drag and drop into scene. Make materials for that. Create material and
change its color an assign it. In scripts folder -- Game folder -- create healthcrate script.
Open it -- this is similar to ammocrate script. Just change ammo to health. In Unity drag
and drop the healthcrate script in the healcrate inspector. Erase the ammocrate script
of it. Put the Container of healthcrate on the Container of healthcrate script in the
inspector. Click on apply the changes. Go to the Player script.
23.Assets include. One audio file for shooting the weapon and other for when the Enemy
dies. Add character model for the Enemy. Add building. Add weapons. Go to Bullet
prefab, drag and drop it to hierarchy. Add component, audio source. Go to the Player
in hierarchy, click in First Person Character. There is an audio listener, this would be use
for hearing sounds. Every moment we should have only one audio listener active at the
same time. It usually come with the camera. In Bullet hierarchy, check the audio
option: Play On Awake. It is going to play as soon as it appears. Open the Audio folder,
drag an drop the shoot audio file into AudioClip of inspector. Press apply. Delete it from
hierarchy.
24.Play the audio when the Enemy dies. Select one of the Enemies in our scene. In
hierarchy inside the ShootingEnemy, create a new game object. Name it DeathSound in
the inspector. Add component, add audio source, drag and drop the dying sound on
Audio Clip. ShootingEnemy need a reference to that audio source. Open the Enemy
script. In hierarchy, in ShootingEnemy, drag and drop the DeathSound into the
DeathSound of the inspector. Apply so the other prefabs get that sound. Disable Play
on Awake in the inspector of ShootingEnemy. The audio is going to be played when the
Enemy dies.
25.Change Enemy. Select an Enemy -- inside Container -- instead of capsule -- go to
Character models. -- select a Character model -- drag and drop inside the Container. --
adjust scale and position. -- delete the capsule. Choose the ShootingEnemy – apply.
26. Adding the Weapon, the Bullet and buildings. In hierarchy go to Gun -- go to weapons
and choose one model. Drag and drop inside the Gun in hierarchy. Adjust scale and
position. Delete the previous model. Select the Bullet prefab, drag and drop in the
GameController. Open the Bullet, open the Container and replace that Sphere with the
Bullet model. Drag and drop it in the Container. Scale and rotate it. Drag and drop the
building models. If we don't want the Enemies access to those models, go to navigation.
In hierarchy and expand the building models. Mark the mesh elements. Mark
Navigation static option in the navigation object. In bake menu press bake again. Make
sure the floor has checked the option navigation static. Press bake, the white areas
show us the Enemy can't navigate. We want to collision with building to avoid passes it.
Select the mesh in the inspector. Add component, add collider, mesh collider. Select
the others and apply mesh collider too.

You might also like