Game Advanced Prototype Version 2
GCC Academy
Hello, everyone
This is Kim Hyun-jin, in charge of FPS game building
In this unit, we will implement
the jump function for the character using user input
Then, we will use Rigidbody
to implement a throwable weapon
and utilize the Raycast function
to create a shooting weapon
Character Jump
First, let's implement the character's jump
Pressing the spacebar will make the character jump
Before implementing the jump,
we need to apply gravity to the player
In the PlayerMove script,
we will create a global variable to handle gravity
A gravity variable is necessary,
and we will also create a variable
to store the vertical velocity affected by gravity
Float gravity
The name is float gravity
We will define float gravity = -20
In reality, gravity has a value of -9.8,
but we do not need
to simulate, at least now,
real-world physics exactly
You can adjust this value
to find what feels appropriate
I will set it to -20
Next, we create a variable for vertical velocity
float yVelocity
Since there is no initial movement, we set it to zero
Then, in the update function,
we will ensure that gravity is continuously applied
before movement calculations
To do this, we will add the gravity value to yVelocity
over time
On our gravity value
Next, using Time.deltaTime,
it ensures that the vertical velocity
accumulates the effects
of gravity per frame in yVelocity
So what do we do?
dir means direction
So dir, and its y value is
yVelocity
Then, the gravity is applied
If we temporarily comment out this gravity application
and test in the editor,
looking up and pressing W will cause the character
to float indefinitely
However, when we re-enable gravity,
undo the comment out,
and test again in the editor,
the character will no longer float upwards
but instead move forward,
as gravity is pulling it downward
Now that gravity is applied,
let's make the player jump
Jumping involves initially moving upward,
reaching a peak, and then falling back down due to gravity
This motion is governed by what?
This jump is governed by gravity
To implement jumping,
we will add another global variable
To determine the jump strength,
let's create a variable called jumpPower
float jumpPower = 10
and can be adjusted as needed
when the jump is implemented
In the update function,
before applying gravity, make some space
Once the spacebar is pressed,
it assigns jumpPower to yVelocity
That's the code we're adding
If input, and among what you have,
use the function GetButtonDown
Open a parenthesis, and use Jump as the parameter
Then, when we press the spacebar,
this function returns true
So this condition is met,
and whatever is inside the parenthesis will happen
And what is it?
Assigning jumpPower to yVelocity
So, to yVelocity,
we add jumpPower
Here, jumpPower is 10
So when we press the spacebar, yVelocity becomes 10
Multiplying gravity with Time.deltaTime
will return a decimal value
So it will be less than this 10
Let's say that we get 9 here
Then, the dir.y value will be 9,
causing the y value to move upwards
This makes the character move upwards as well
In the next frame, yVelocity of 9
may become 8,
slightly reducing the upward movement
Eventually, this value decreases further,
reversing the direction at one point
and causing the character to fall back down in a jump
Let's switch to the editor and play the scene
When we press the spacebar,
we can see that the character jumps
If the jump height feels too high,
we can reduce the jump power
To make it easier to adjust,
we change the jumpPower variable to public,
then go back to the editor, select the Player object,
and go to PlayerMove
and change JumpPower to 5
Let's test again,
and observe that the character now jumps with a lower height
It can even jump on this block
However, there's an issue
Let's go up to this block
When we do,
let's look at the scene view
When the character moves forward here,
it should naturally fall if there's no ground
So the character should fall down
But when we test it,
see what happens
The character just teleports down
This happens
because while standing on the ground,
the yVelocity, though it works perfectly,
continues to decrease due to gravity,
even though the character is not moving downward
So over time,
this value we have at yVelocity will drop down
and accumulate into a very large negative number,
like -10000, or even -100000
So this yVelocity value
is a big negative number
When the character finally moves off the edge,
this extreme value
causes it to drop instantly
So what happens?
The character appears as though it teleports
So how do we fix this?
Whenever the character is on the ground,
we reset yVelocity to zero
This little code will solve the problem
Before we press the spacebar,
if the character is touching the ground,
set yVelocity to 0
That's the condition we'll be adding
Whether the character is touching the ground
can be checked at CharacterController
So of all properties,
it has isGrounded
It's a bool type, which returns true if the character is on the ground
and false if it is in the air
If isGrounded is true,
we set yVelocity to 0
So, yVelocity = 0
Let's return to the editor and test again
The character is up here again
Let's fall down
We've been sitting here for a while now
Now, let's move forward
Now it falls naturally, instead of teleporting
It was a very natural motion
Throwable weapon
Now, let's create a throwable weapon
We will make a grenade-like object
In the Hierarchy window, click the + button,
select 3D Object > Sphere,
and rename it to Bomb
When the right mouse button is pressed,
the bomb will be created
and launched forward, in the direction of the camera
So the bomb will be moving this way here
Instead of moving in a straight line indefinitely,
what does gravity do?
The bomb should fall naturally
To assign such gravity,
we could manually implement gravity in the script
by writing the code out
But Unity provides a built-in Rigidbody component
that handles physics calculations, including gravity
To apply it, select the Bomb object,
go to Add Component,
search for Rigidbody,
make sure it's not Rigidbody2D
Select Rigidbody
Now, check the Use Gravity option
If checked,
the bomb will fall due to gravity when played
If unchecked, the bomb will not be affected by gravity
At this stage, the bomb is not fully functional yet
Before finalizing it, let's apply that when we right-click,
it will spawn at a location and launch
in the direction the camera is facing
To do this, we convert Bomb into a Prefab,
allowing it to be instantiated dynamically
To create the prefab, select the Assets folder,
then click the + button in the Project window
and create a new folder named Prefabs
Drag the Bomb object from the Hierarchy
Drag this Bomb
into this folder
to convert it into a prefab
Next, delete the Bomb object from the Hierarchy
Then, we will create a script
to instantiate and launch the bomb forward
for our player, or the character
In the Assets folder, navigate to the Scripts folder
and create a new C# script by clicking the + button
Name this script PlayerFire
After that, select the Player object in the Hierarchy,
drag the PlayerFire script onto it,
and attach it to the Player
so that it is properly integrated
Now, open the PlayerFire script
To fire bombs, we need two global variables:
The bomb,
and the fire position
from which the bomb will be launched
We created our Bomb prefab
by drag-and-dropping GameObject
Since the bomb prefab is an external asset,
its data type must be GameObject
Mark it as public
so that we can assign it in the Inspector
And the data type is GameObject
Then, name the varible
Let's name it bombFactory
Let's create GameObject for the launch location
and add it in there
public GameObject firePosition;
We haven't created the fire position yet,
but after writing this code,
we will set it up in the editor
In the Update function,
we check if the right mouse button is pressed
If so, we create a bomb
at Bomb Prefab
Next, we instantiate that bomb
at the fire position
To detect right-click input, we use this
If, Input, and of all the things it has,
we use the function GetMouseButtonDown
We put them in parentheses, and we put a number here
Using 0 will return true
when we left-click
Using 1,
it returns true
when we right-click
We can also add 2, which returns true
when we click on the mouse wheel
Since we decided that we're using the right click,
we just add 1
Then, we do these two
Instantiate, open up a parenthesis,
and add our bomb prefab, the bombFactory
This creates a copy of the bomb prefab,
and we store the reference in bomb
Now, we need to get that value
GameObject bomb =
That's how we can answer that
All the result is saved in this variable bomb
We can change the position with this variable
So we use bomb.transform.position
So we approach position
to set it up, but how?
We'll set it as the position value
of transform that firePosition owns
Let's return to the editor and select the Player object
Under Inspector, Bomb Factory field is None
Now, to the Assets folder here,
the Bomb prefab from the Prefabs folder
Drag this Prefab into this field
Just like that
We haven't created fire position yet, so we should now
In the Hierarchy, select the Player object,
right-click, and choose Create Empty
Rename this object to FirePos
Then, move it to a suitable position above the player's head,
just like that
Let's try around 1.8 units high
Finally, select the Player object again,
drag FirePos
into the Fire Position field in the Inspector
Now, when we press the right mouse button,
a bomb will be instantiated
So what do we do with this?
We put it at the fire position
All this has been coded in what we have
Let's play and test it
When right-clicking, bombs are created
and they drop
More bombs appear and fall
Currently, the bombs collide with the player,
so it looks like this
But we will later implement a fix to prevent this
Now, we implemented the bomb instantiation
However, at this stage, the bombs are only being created,
not actually being launched
Now, let's make the bomb launch in the direction
of the camera, similar to a grenade throw
Go to the PlayerFire script
and define a new variable for the throw power
Let's stary with public float
Name the variable as throwPower
Let's add around 1000
This force is applied
for the gravity to the bomb
using Rigidbody
We can also use it to apply force
We can create the bomb using a right-click here,
so let's add the force application at the bottom
So we bring in the Rigidbody component
from the bomb using this method up here
And we use GetComponent for the force
All in the direction of the camera
Let's now define a variable to store Rigidbody
Data type is Rigidbody
Let's name it as rb
Next, we bring
GetComponent from bomb
Since we have Rigidbody
attached to bomb,
we need access to the compoennt
using this variable bomb
What if we didn't have this part?
It means we're getting it from the player
This will result in an error,
because our player has no Rigidbody
So we ask bomb
to use Getcomponent function
to retrieve the component that it already has
In a set of angle brackets,
add in the component type we want
Since we want Rigidbody,
add Rigidbody, type in the parentheses
Use a semicolon
So for the variable rb,
it has the Rigidbody component
attached to the bomb
So of all functions that rb has,
there is AddForce
This can apply force
So we add force and direction here
So to the camera,
the main camera,
we use transform
and forward, because we need the force forward
This will give us a very little force,
because it is 1
So we use * and multiply it by the variable throwPower
If this force is too weak or too strong,
we can edit it at the Inspector
Go back to Editor and play
Right click,
and the bombs are flying around
Select Player,
and adjust the throwPower in the Inspector to 700
Now, we see that the throw distance has decreased
Currently, the bomb just bounces
when it hits the ground or walls
Let's modify it a little, so that
it disappears on impact
In the Scripts folder,
create a new C# script
and name it BombAction
Next, go to Assets folder,
choose Prefabs folder,
and get the Bomb prefab
In the Inspector, click Add Component,
search for BombAction we just created,
and attach it
Double click to open it
When this bomb collides with any object,
it will destroy itself using this code
So search for oncoll
and we get OnCollisionEnter
Let's complete this function
This function is called
whenever something has a physical collision
And, what do we want here?
Destroy itself
Destroy(gameObject);
This code will make the object destroy itself
Now, play again
The bomb disappears upon hitting the ground
It does the same with this block
Next, let's create a shooting weapon
This will be using Ray
Let's say this is the camera
We will cast a Ray from the camera's position
and moving forward
It's like laser,
which keeps moving forward
If there is a wall here,
this Ray will hit the wall, right?
Then, we can get this impact location
We can use left-click
to create Ray, shoot it,
and add a visual effect on the impact location
like sparks or bullet impact
This will look like a fast bullet
traveling until it hits the surface
Using this,
let's implement the shooting weapon
First, in the PlayerFire script,
go to the existing bomb-throwing function
Instead of keeping it in Update,
we will move it to a separate function
Below Update, add void Firebomb
Now, use Ctrl+X to cut the bomb-throwing code
from Update and paste it inside the FireBomb function
Finally, call the FireBomb function
inside the Update function
Now, the behavior remains the same
Similarly, we will create a function
for the shooting weapon
void FireRay
It checks if the left mouse button is pressed
If so, this Ray will move
from the camera's position and forward
Next, this Ray will be fired
sing the function Raycast
Once this Ray hits something,
we add the visual effect on that position
That's the order of this coding
If, of all functions in Input,
we use GetMouseButtonDown
And with 0, or the left-click,
we get true
Inside parentheses, use 2, 3, 4, and 5
Everything goes inside
Let's create a Ray now
Its data type is Ray
For that, we create a variable called ray with a lower case
Let's create a new Ray here
When creating a Ray, we can specify two parameters
We can have Starting position and the direction
Since we want the ray to originate from the camera
and move in the direction the camera is facing,
Camera.main, and then
transform.position
And after a comma,
Camera.main
Next, transform.forward
This is how we create a Ray
Next, we use Raycast
to check for collisions along this
Raycast is under Physics
So start with Physics
and add Raycast
First, add ray
Next, the second parameter
is the direction in which
the ray will travel in the case of the collision
The variable will set this information up
So we need to create the variable
The data type is RaycastHit
Let's name the variable hitInfo
To the second parameter,
use out for the hinInfo
Raycast returns true
if this ray has hit any surface
Next, this hitInfo
will contain the information about that position
So these two, the third and the fourth,
work at the same time with Raycast
So we can use the if statement
for our variable, Physics.Raycast
If the ray collides with an object
after traveling in the camera direction,
raycast returns true
Next, it stores the impact details
in this variable, hitInfo
We need to display a particle effect at the impact location
However, since we don’t have
a particle asset ready
We will first verify
that the raycast is working correctly,
or if our ray has collided with a game object
by printing debug information
print, hitInfo
To this variable, hitInfo,
there is information on the collision detail
So using hitInfo,
we can bring in the name of the game object
so, hitInfo.transform
This will give us the name
Now, use + and then a comma
Next, + and the collision point
so hitInfo, and
the location is saved in the variable point
Since we have the variable FireRay,
let's update it and continue
FireRay
Save, and come back to the editor
Enable the console window
If this Collapse is checked
in this gray area, click to remove
Press Ctrl+P to run
Left-click, and in this game view,
we get Ray traveling from the center
If I left-click facing this wall,
we get the name Wall
(-0.12, 0.92, 7.47)
We get the coordinate values for the collision point
If you slightly shift your view toward the left edge
and click the left mouse button
you will notice that the Wall object is still detected
But the collision point has changed
As a result, the coordinates displayed in the console
are different from the previous click
Now, we will use this collision point
to display a particle effect
at the exact impact location
Open Unity's Asset Store
Go to Window > Asset Store from the top menu
Go to the Asset Store
And search for
war fx
Select this
Add it to your assets
Click OK for this popup window
Then, you will get another window
Open it using Unity
Next, open Unity Editor
It opens Package Manger window,
so that we can download our war fx
Download it
Next, we get Import and Re-Download
We get two buttons
Click on Import
Then, we get a list of assets to import
Import everything
Click Import again
Next, go to the Project window
Find a folder named JMO Assets
This is where we can see our war fx
Double click on _Effects folder to enter
We have a folder named Bullet Impacts
Go inside the folder,
and we have various particles
Let's use WFX_BImpact
And go with Concrete NoCollision
Drag and drop this prefab to Hierarchy
In the Inspector,
there is additional script
Let's remove this script
Hover over the script name,
right click
and choose Remove Component
Rename it to BulletImpact
We will make this BulletImpact in Hierarchy
into our own Prefab
Go to the Prefabs folder
drag it down here
Once we get this popup window, click on Origin Prefab
Now, this Prefab from the Asset Store
has its original retained
Using this, we just made
a new Prefab for ourselves
Remove this BulletImpact from the Hierarchy
Next, select the BulletImpact prefab
In the Inspector, make sure Play On Awake
is enabled
This option ensures that the effect plays
automatically when instantiated
Now, for this Particle System,
go to the PlayerFire script
Right now, when the bullet collides with an object,
we are only printing its information to the Console
Now, comment out the debug print statement
Now, let's display a bullet impact effect
at the exact location where the ray collides
First, we need to create a global variable
We need our BulletImpact prefab
public GameObject bulletImpactFactory;
Later, we will assign this prefab
in Unity’s Inspector after writing out the code
Go back to the FireRay() function
and add the following code under number five
Then, we will put the effect
at the collision point
This is the order we will take
Instantiate
Next, add our bullet impact effect prefab
bulletImpactFactory
GameObject bulletImpact =
That's how we get it
Next, for bulletImpact,
we use tranform.position
To change the position
Where should it go?
To hitInfo.point
Save the script, return to the editor
Select the Player GameObject
In the Inspector, locate the Player Fire component
Find the Bullet Impact Factory field
Drag the BulletImpact prefab
into this field
Next, let's play it
When you click the left mouse button,
though it may not be very visible from a distane,
you can see the debris effect appearing
Similarly, if you shoot at the floor, the debris effect is distinctly visible
One issue here is that after the debris effect is fully displayed,
it remains on the screen instead of disappearing
Another problem arises
when shooting at a wall While the effect appears rich and full on the floor,
doing it on the wall
only shows a partial amount of it
This happens because
the debris effect shoots upward when it collides with the wall
As a result, one half of the effect remains visible outside the wall,
but the other half gets embedded inside the wall,
making it invisible
To ensure the effect appears fully outside the wall,
we need to adjust it accordingly
so that we get that same effect
Let's adjust these two things
Open the PlayerFire script
First, set the bulletImpact to be destroyed after 2 seconds
sing the Destroy(bulletImpact); function will do it
As we see, it immediately deletes the effect upon creation
To this Destory function, we can add a comma
to add a second parameter
If we add the number 2,
it destroys bulletImpact,
after two seconds
So bulletImpact, after showing its effect,
disappears in two seconds
Next, we need to solve the issue
where the effect gets embedded inside the wall
Let's bring it to face the direction of the wall
When the Ray collides with a vertical surface,
the debris effect currently spreads outward,
which makes this part invisible
So what do we do with it?
We need to orient the effect in a direction
perpendicular to the wall
What if it hits the floor?
The effect should spread outward
based on the normal vector of the surface
So, there are perpendicular vectors to this surface
These perpendicular vectors
are called Normal Vectors or simply Normals
This Normal Vector is already calculated within the hitInfo variable
We will modify its forward direction
to match the Normal Vector of the collided surface
So, bulletImpact,
transform.forward
equals to hitInfo.normal;
Save it
Go back to the editor to play it
Left click,
and we get this impact effect
Now, underHierarchy,
the effect disappears after two seconds
just as we see, like so
When firing with Raycast,
it's difficult to aim precisely
To make targeting easier, we will add a UI element
to serve as a crosshair at the center
In the Hierarchy, click the + button
Select UI > Image
Rename the newly created Image to Crosshair
In the Inspector, adjust:
Width to 10, and Height to 10
Change the color of the image
to your preferred aiming color
Save the scene and play again
Now, you can use the red crosshair as a reference point
when firing with Raycast
This gives us the bullet impact effect
exactly where we're aiming
Let's go over what we have learned today
Character Jumping Gravity applied to the player object: yVelocity += gravity * Time.deltaTime; dir.y = yVelocity;
Jump when pressing the space bar: if (Input.GetButtonDown("Jump")) { yVelocity = jumpPower; }
Reset yVelocity when the player is on the ground to ensure smooth falling:
if (cc.isGrounded) { yVelocity = 0; }
Throwable Weapon (Grenade) Create a Bomb object as a Prefab and throw it in the camera's direction when right-clicking:
if (Input.GetMouseButtonDown(1)) (0): Returns true when the left mouse button is clicked
(1): Returns true when the right mouse button is clicked (2): Returns true when the mouse wheel button is clicked
Create a bomb from the bomb Prefab GameObject bomb = Instantiate(bombFactory);
Place the created bomb at the firing position bomb.transform.position = firePosition.transform.position;
Create the FirePosition object Add an empty GameObject to the Player
Change the y-value of the FirePos object's transform position to 1.8 Drag and drop FirePos into the Fire Position of the Player object
Launch in the direction the camera is facing Get the Rigidbody component from the created bomb Rigidbody rb = bomb.GetComponent();
Apply force using the retrieved component rb.AddForce(Camera.main.transform.forward * throwPower);
Make the bomb disappear after collision OnCollisionEnter() function is called when a physical collision occurs Destroy();
Define the shooting weapon function Implement void FireRay() function to handle shooting Left mouse click → Fire a Ray and insert an impact effect at
if (Input.GetMouseButtonDown(0)) Create a Ray moving from the camera position in the forward direction
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward); RaycastHit hitInfo;
Fire the Ray using the Raycast function if (Physics.Raycast(ray, out hitInfo))
For collisions, if (Physics.Raycast(ray, out hitInfo)
Create an impact effect GameObject bulletImpact = Instantiate(bulletImpactFactory);
Place the created impact effect at the collision position bulletImpact.transform.position = hitInfo.point;
Destroy the impact effect after 2 seconds to prevent clutter Destroy(bulletImpact, 2)
The impact effect is insufficiently displayed when colliding with a wall
Adjust the impact effect orientation to align with the normal vector of the hit surface bulletImpact.transform.forward = hitInfo.normal;