pacman - career center east video game (harman)videogame-harman.weebly.com › ... ›...
TRANSCRIPT
Note: I have started this exercise for you so you do not have to make all of the box colliders.
maze was created, open the file named “unity_pacman_create_maze.
Adding Pac-Man
The Pac-Man Sprite
Now it's time for the most important part of our game: Pac
direction:
- right
- left
- up
- down
All the animations are in one image, where
We will use the following Import Settings for it:
Slicing the Pac-Man Sprite
It's important to set the Sprite Mode to Multiple
Let's open the Sprite Editor by clicking the button:
Pacman
Note: I have started this exercise for you so you do not have to make all of the box colliders. If you
“unity_pacman_create_maze.”
Now it's time for the most important part of our game: Pac-Man. We will need one animation for each movement
there is one animation per row. The image is called
for it:
Multiple, which tells Unity that there is more than one Pac
by clicking the button:
If you want to see how the
Man. We will need one animation for each movement
there is one animation per row. The image is called pacman.png.
, which tells Unity that there is more than one Pac-Man in our Sprite.
Now we can tell Unity where each Pac-Man animation slice is located in our Sprite. We will select
as 16 x 16 Grid and press the Slice button afterwards:
Once the Sprite was sliced, we can close the Sprite Editor again. If Unity asks us about
we will click on Apply.
As a result we now have 12 slices under our Pac
Creating the Pac-Man Animations
Okay so now that we have the animation slices, we can create our 4 animations from it. As a reminder, here are the
animations that we will need:
• right (Slice 0, 1 and 2)
• left (Slice 3, 4 and 5)
• up (Slice 6, 7 and 8)
• down (Slice 9, 10 and 11)
Man animation slice is located in our Sprite. We will select
button afterwards:
Once the Sprite was sliced, we can close the Sprite Editor again. If Unity asks us about Unapplied Import Settings
As a result we now have 12 slices under our Pac-Man Sprite in theProject Area:
Okay so now that we have the animation slices, we can create our 4 animations from it. As a reminder, here are the
Man animation slice is located in our Sprite. We will select Slice and then slice it
Unapplied Import Settings then
Okay so now that we have the animation slices, we can create our 4 animations from it. As a reminder, here are the
Let's create the right animation. We will begin by selecting the first three slices in the
And then dragging them into the Scene:
Now whenever we drag several slices into the Scene, Unity
hence why it automatically asks us where to save the animation. Let's save it as
new PacmanAnimation folder.
Unity just added a pacman_0 GameObject to the
animation. We will begin by selecting the first three slices in the Project Area
Now whenever we drag several slices into the Scene, Unity will know that we want to create an animation from them,
hence why it automatically asks us where to save the animation. Let's save it as right.anim in a
GameObject to the Scene and two files to the Project Area:
Project Area:
will know that we want to create an animation from them,
in a
The first file is the animation state machine that specifies things like the animation speed and blend trees. The second
one is the animation itself.
We will repeat this process for the rest of the animations
down).
Here is what our Hierarchy looks like afterwards:
Cleaning up after Unity
Unity created one GameObject for each animation, but we only need the first one as we will see soon. Let's select the
other 3 and then right click and delete them:
A similar thing happened in our Project Area
The first file is the animation state machine that specifies things like the animation speed and blend trees. The second
We will repeat this process for the rest of the animations (Slice 3, 4, 5 for left; Slice 6, 7, 8 for up and Slice 9, 10, 11 for
looks like afterwards:
Unity created one GameObject for each animation, but we only need the first one as we will see soon. Let's select the
them:
Project Area. We now have 4 animations and 4 animation state machines:
The first file is the animation state machine that specifies things like the animation speed and blend trees. The second
6, 7, 8 for up and Slice 9, 10, 11 for
Unity created one GameObject for each animation, but we only need the first one as we will see soon. Let's select the
animation state machines:
Again we only need one animation state machine, so let's delete the other three:
The Pac-Man Animation State Machine
Right now we have 4 animation files, but Unity doesn't know when to play which animation yet. The solution to our
problem is part of Unity's unbelievably powerful
that has 4 states:
• right
• left
• up
• down
We will also add Transitions so Unity knows when to switch from one animation state to another.
Note: Unity will play the right animation over and over again while in
switch to another state. Unity does all of that automatically, all we have to do is notify it about Pac
direction from within a Script later on.
Okay so let's double click the pacman_0 animation state machine file in our
Again we only need one animation state machine, so let's delete the other three:
Right now we have 4 animation files, but Unity doesn't know when to play which animation yet. The solution to our
problem is part of Unity's unbelievably powerful Mecanim animation system. We will need a animation state machine
so Unity knows when to switch from one animation state to another.
animation over and over again while in right state. It will use Transitions
state. Unity does all of that automatically, all we have to do is notify it about Pac
animation state machine file in our Project Area:
Right now we have 4 animation files, but Unity doesn't know when to play which animation yet. The solution to our
animation system. We will need a animation state machine
so Unity knows when to switch from one animation state to another.
Transitions to know when to
state. Unity does all of that automatically, all we have to do is notify it about Pac-Man's movement
Now we can see the state machine in the Animator
Creating the Other States
The right state is already in the Animator, so let's add the
the ShipAnimation folder from our Project Area
This process can be repeated for the remaining two states:
The big deal about Mecanim is that it will take care of the animation states on its own, fully automatically. All we have to
do is tell Mecanim to watch out for our Pac
between animation states on its own, without us having to do anything.
Animator:
state is already in the Animator, so let's add the left state by simply dragging the left.anim
Project Area into the Animator:
can be repeated for the remaining two states:
The big deal about Mecanim is that it will take care of the animation states on its own, fully automatically. All we have to
do is tell Mecanim to watch out for our Pac-Man's movement direction, nothing more. Mecanim will then switch
between animation states on its own, without us having to do anything.
left.anim file from
The big deal about Mecanim is that it will take care of the animation states on its own, fully automatically. All we have to
e. Mecanim will then switch
Creating the Parameters
So let's tell Mecanim that it should watch out for Pac Man's movement direction. A movement direction is of type
Vector2, the following image shows some possible movement directions:
Our Pac-Man will only have 4 movement directions
4 Transitions in our animation state machine:
• If DirY > 0 then go to up (like DirY=1, DirY=2, DirY=3 and so on)
• If DirY < 0 then go to down (like DirY=-
• If DirX > 0 then go to right (like DirX=1, DirX=2, DirX=3 and so on)
• If DirX < 0 then go to left (like DirX=-1, DirX=
Let's take a look at the left area of the Animator and select the
Here we will click on the + at the right and then add one Parameter of type
Parameter of type Float with the name DirY
Later on we can set those parameters from within a Script by writing:
GetComponent<Animator>().SetFloat("DirX"
GetComponent<Animator>().SetFloat("DirY"
Creating the Transitions
We want Unity to automatically switch to different animation states based on
achieve just that. For example, we could add a Transition from
considered best practice to have a small error tolerance because floating point comparison
why we will use DirX > 0.1 instead.
Now we would also have to use a DirX > 0.1
work, we can use Unity'sAny State.
The Any State stands for literally any state. So if we create a Transition from
creating a Transition fromleft, up and down
So let's tell Mecanim that it should watch out for Pac Man's movement direction. A movement direction is of type
ng image shows some possible movement directions:
Man will only have 4 movement directions (up, down, left, right). Which means that we only need the following
in our animation state machine:
=1, DirY=2, DirY=3 and so on)
-1, DirY=-2, DirY=-3 and so on)
(like DirX=1, DirX=2, DirX=3 and so on)
1, DirX=-2, DirX=-3 and so on)
Let's take a look at the left area of the Animator and select theParameters tab:
at the right and then add one Parameter of type Float with the name
DirY:
can set those parameters from within a Script by writing:
"DirX", 0);
"DirY", 0);
We want Unity to automatically switch to different animation states based on those parameters. Transitions are used to
achieve just that. For example, we could add a Transition from left to right with the Condition that
considered best practice to have a small error tolerance because floating point comparison is not always perfect, hence
DirX > 0.1 Transition from every other state to right. To save us from doing all this
any state. So if we create a Transition from Any State to right
down to right.
So let's tell Mecanim that it should watch out for Pac Man's movement direction. A movement direction is of type
. Which means that we only need the following
with the name DirX and another
those parameters. Transitions are used to
with the Condition that DirX > 0. However it's
is not always perfect, hence
. To save us from doing all this
right then it's the same as
Let's right click the Any State and select Make Transition
Now we can click on the white arrow and take a look at the
in other words, when it should switch). We will set it to
Note: press the + at the bottom right to add a Condition.
Make Transition. Afterwards we can drag the white arrow onto the
Now we can click on the white arrow and take a look at the Inspectorwhere we can modify the Transition's
. We will set it to DirX > 0.1:
at the bottom right to add a Condition.
. Afterwards we can drag the white arrow onto the right state:
where we can modify the Transition's Condition (or
Let's also disable Can Transition To Self in the
Note: this avoids weird situations where an animation would be restarted all the time while holding down a movement
key.
As result, whenever Pac-Man walks to the right
animation.
We will add 3 more Transitions:
• Any State to left with the Condition DirX <
• Any State to up with the Condition DirY > 0.1
• Any State to down with the Condition
Here is how it looks in the Animator now:
in the Settings:
Note: this avoids weird situations where an animation would be restarted all the time while holding down a movement
Man walks to the right (DirX > 0.1), the animator will switch to the right
DirX < -0.1
DirY > 0.1
DirY < -0.1
Note: this avoids weird situations where an animation would be restarted all the time while holding down a movement
right state and play the
We are almost done with our animation state machine. There is one last adjustment to be made here, so let's select all
states and then modify their Speed in the Inspector
If we press Play then we can already see the
Pac-Man Naming and Positioning
We want to keep everything nice and clean, so let's select the
it to pacman (right click it and select rename, or
We will also change its position to (14, 14) so it's not outside the maze anymore:
Pac-Man Physics
Right now Pac-Man is only an image, nothing more. He is not part of the physics world, things won't collide with him and
he can't move or anything else. We will need to add a
things will collide with Pac-Man instead of walking right through him.
Pac-Man is also supposed to move around. A Rigidbody takes care of stuff like grav
make things move. As a rule of thumb, everything in the physics world that is supposed to move around needs
a Rigidbody.
We are almost done with our animation state machine. There is one last adjustment to be made here, so let's select all
Inspector so that the animation doesn't look too fast:
then we can already see the right animation:
We want to keep everything nice and clean, so let's select the pacman_0GameObject in the Hierarchy
(right click it and select rename, or press F2) :
so it's not outside the maze anymore:
Man is only an image, nothing more. He is not part of the physics world, things won't collide with him and
anything else. We will need to add a Collider to make him part of the physics world, which means that
Man instead of walking right through him.
Man is also supposed to move around. A Rigidbody takes care of stuff like gravity, velocity and other forces that
make things move. As a rule of thumb, everything in the physics world that is supposed to move around needs
We are almost done with our animation state machine. There is one last adjustment to be made here, so let's select all
so that the animation doesn't look too fast:
Hierarchy and then rename
Man is only an image, nothing more. He is not part of the physics world, things won't collide with him and
to make him part of the physics world, which means that
ity, velocity and other forces that
make things move. As a rule of thumb, everything in the physics world that is supposed to move around needs
Let's select the pacman GameObject in the
as Add Component->Physics 2D->Rigidbody 2D
following image:
Alright, Pac-Man is now part of the physics world. He will collide with other things and other things w
This will also cause the OnCollisionEnter2D
The Movement Script
Alright now there are several ways to make Pac
checks for Arrow-Key presses and then move Pac
wouldn't feel very good.
Instead we will try to be more exact. Whenever the player presses one of the Arrow
1 unit into the desired direction. The Pac-Dots
it only makes sense that Pac-Man always moves exactly one unit.
Let's select pacman in the Hierarchy and press
select CSharp as language. We will also move the Script into a new
clean):
Alright let's double click the Script so it opens:
using UnityEngine;
using System.Collections;
public class PacmanMove : MonoBehaviour
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Hierarchy, select Add Component->Physics 2D->Circle
Rigidbody 2D. It's important that we use exactly the same settings as shown in the
Man is now part of the physics world. He will collide with other things and other things w
OnCollisionEnter2D function to be called in any Script that is attached to Pac
Alright now there are several ways to make Pac-Man move. The easiest way would be to create a Script
Key presses and then move Pac-Man a bit up/down/left/right when needed. This would work, but it
Instead we will try to be more exact. Whenever the player presses one of the Arrow-Keys, Pac-
Dots (the food) will also be positioned with a 1 unit distance between them, so
Man always moves exactly one unit.
and press Add Component->New Script, name it PacmanMove
as language. We will also move the Script into a new Scripts folder in the Project Area
Alright let's double click the Script so it opens:
MonoBehaviour {
Circle Collider 2D as well
. It's important that we use exactly the same settings as shown in the
Man is now part of the physics world. He will collide with other things and other things will collide with him.
function to be called in any Script that is attached to Pac-Man.
Man move. The easiest way would be to create a Script that simply
Man a bit up/down/left/right when needed. This would work, but it
-Man should move exactly
will also be positioned with a 1 unit distance between them, so
PacmanMove and
Project Area (just to keep things
The Start function is automatically called by Unity when starting the game. The Update function is automatically called
over and over again, roughly 60 times per second (this depends on the current frame rate, it can be lower if there are a
lot of things on the screen).
There is yet another type of Update function, which is FixedUpdate. It's also called over and over again, but in a fixed
time interval. Unity's Physics are calculated in the exact same time interval, so it's always a good idea to
use FixedUpdate when doing Physics stuff:
using UnityEngine;
using System.Collections;
public class PacmanMove : MonoBehaviour {
void Start() {
}
void FixedUpdate() {
}
}
We will need a public variable so that we can modify the movement speed in the Inspector later on:
using UnityEngine;
using System.Collections;
public class PacmanMove : MonoBehaviour {
public float speed = 0.4f;
void Start() {
}
void FixedUpdate() {
}
}
We will also need a way to find out if Pac-Man can move into a certain direction or if there is a wall. So for example if we
would want to find out if there is a wall at the top of Pac-Man, we could simply cast a Line from one unit above of Pac-
Man to Pac-Man and see if it hit anything. If it hit Pac-Man himself then there was nothing in-between, otherwise there
must have been a wall.
Here is the function:
bool valid(Vector2 dir) {
// Cast Line from 'next to Pac-Man' to 'Pac-Man'
Vector2 pos = transform.position;
RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
return (hit.collider == collider2D);
}
Note: we simply casted the Line from the point next to Pac-Man (pos + dir) to Pac-Man himself (pos).
We will also need a function that makes Pac-Man move 1 unit into the desired direction. Of course we could just do:
transform.position += dir;
But this would look too abrupt because it's such a huge step. Instead we want him to go there smoothly, one small step
at the time. Let's store the movement destination in a variable and then use FixedUpdate to go towards that destination
step by step:
using UnityEngine;
using System.Collections;
public class PacmanMove : MonoBehaviour {
public float speed = 0.4f;
Vector2 dest = Vector2.zero;
void Start() {
dest = transform.position;
}
void FixedUpdate() {
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transform.position, dest, speed);
GetComponent<Rigidbody2D>().MovePosition(p);
}
bool valid(Vector2 dir) {
// Cast Line from 'next to Pac-Man' to 'Pac-Man'
Vector2 pos = transform.position;
RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
return (hit.collider == collider2D);
}
}
Note: we used GetComponent to access Pac-Man's Rigidbody component. We then use it to do the movement (we
should never use transform.position to move GameObjects that have Rigidbodies).
Let's also watch out for arrow key presses whenever we are not moving.
Note: we are not moving if the current position equals the destination.
Here is our FixedUpdate function with Input checks:
void FixedUpdate() {
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transform
GetComponent<Rigidbody2D>().MovePosition
// Check for Input if not moving
if ((Vector2)transform.position == dest) {
if (Input.GetKey(KeyCode.UpArrow) &&
dest = (Vector2)transform.position +
if (Input.GetKey(KeyCode.RightArrow)
dest = (Vector2)transform.position +
if (Input.GetKey(KeyCode.DownArrow)
dest = (Vector2)transform.position -
if (Input.GetKey(KeyCode.LeftArrow) &&
dest = (Vector2)transform.position -
}
}
Note: transform.position is casted to Vector2
Vector2.up means left and -Vector2.right means
If we save the Script and press Play then we can now move Pac
Here is our FixedUpdate function with Input checks:
transform.position, dest, speed);
MovePosition(p);
&& valid(Vector2.up))
+ Vector2.up;
&& valid(Vector2.right))
+ Vector2.right;
) && valid(-Vector2.up))
Vector2.up;
&& valid(-Vector2.right))
Vector2.right;
Vector2 because this is the only way to compare or add another Vector2. Also
means down.
then we can now move Pac-Man with the arrow keys:
because this is the only way to compare or add another Vector2. Also -
Setting the Animation Parameters
Right now we can perfectly move Pac-Man around the maze, but the animator
problem, let's just modify our code to calculate the current movement direction and then set the animator parameters:
void FixedUpdate() {
// Move closer to Destination
Vector2 p = Vector2.MoveTowards(transfo
GetComponent<Rigidbody2D>().MovePosition
// Check for Input if not moving
if ((Vector2)transform.position == dest) {
if (Input.GetKey(KeyCode.UpArrow) &&
dest = (Vector2)transform.position +
if (Input.GetKey(KeyCode.RightArrow)
dest = (Vector2)transform.position +
if (Input.GetKey(KeyCode.DownArrow)
dest = (Vector2)transform.position -
if (Input.GetKey(KeyCode.LeftArrow) &&
dest = (Vector2)transform.position -
}
// Animation Parameters
Vector2 dir = dest - (Vector2)transform.position
GetComponent<Animator>().SetFloat("DirX"
GetComponent<Animator>().SetFloat("DirY"
}
Note: we calculated the current movement
current position from the destination.
And that's all there is to it. If we save the Script and press
Drawing Pac-Man in the Foreground
Before we start to work on the Pac-Dots, we should make sure that Pac
making a 2D game, so there isn't really any
pleases. Let's make sure that Unity always draws Pac
There are two ways to do this. We could either change the
the Order in Layer property. The Sorting Layer
simply change the Order in Layer to 1:
Man around the maze, but the animator doesn't play all the animations yet. No
problem, let's just modify our code to calculate the current movement direction and then set the animator parameters:
transform.position, dest, speed);
MovePosition(p);
&& valid(Vector2.up))
+ Vector2.up;
&& valid(Vector2.right))
+ Vector2.right;
) && valid(-Vector2.up))
Vector2.up;
&& valid(-Vector2.right))
Vector2.right;
position;
"DirX", dir.x);
"DirY", dir.y);
direction with basic vector math. All we had to do was subtract the
the Script and press Play then we can now see the proper animations:
Dots, we should make sure that Pac-Man is always drawn in
Z order like in 3D games. This means that Unity just draws objects as it
pleases. Let's make sure that Unity always draws Pac-Man in front of everything else.
We could either change the Sprite Renderer's Sorting Layer property or we could change
Sorting Layer is important for bigger games with far more objects. For us it's enough to
doesn't play all the animations yet. No
problem, let's just modify our code to calculate the current movement direction and then set the animator parameters:
ection with basic vector math. All we had to do was subtract the
then we can now see the proper animations:
Man is always drawn in front of them. We are
order like in 3D games. This means that Unity just draws objects as it
property or we could change
is important for bigger games with far more objects. For us it's enough to
Note: Unity draws objects sorted by their order. It starts with the lowest order and continues with higher orders. So if
Pac-Man has the order 1 then he's always drawn after the maze and the food and anything else with order 0. And
because he's drawn after everything else, he's automatically in front of everything else.
The Pac-Dots
The little dots that Pac-Man can eat are called Pac
drawing a small 2x2px image of a Pac-Dot: It is in your sprites folder named
Afterwards we can drag it into the Scene. We want to be notified when Pac
is select Add Component->Physics 2D->Box Collider 2D
Unity draws objects sorted by their order. It starts with the lowest order and continues with higher orders. So if
Man has the order 1 then he's always drawn after the maze and the food and anything else with order 0. And
ything else, he's automatically in front of everything else.
Man can eat are called Pac-Dots. Some might now them as 'fruits' or just 'food'. We will begin by
It is in your sprites folder named “pacdot.png.”
. We want to be notified when Pac-Man walks over a Pac
Box Collider 2D in the Inspector and then select Is Trigger
Unity draws objects sorted by their order. It starts with the lowest order and continues with higher orders. So if
Man has the order 1 then he's always drawn after the maze and the food and anything else with order 0. And
Dots. Some might now them as 'fruits' or just 'food'. We will begin by
Man walks over a Pac-Dot. All we have to do
Is Trigger:
Note: a Collider with IsTrigger enabled only receives collision information, it does not physically collide with other things.
Unity will automatically call the OnTriggerEnter2D function whenever Pac-Man or one of the Ghosts walk over the Pac-
Dot.
So let's select Add Component->New Script, name it Pacdot, selectCSharp, move it into our Scripts folder and then open
it:
using UnityEngine;
using System.Collections;
public class Pacdot : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
We won't need the Start or the Update function, so let's remove both of them. Instead we will use the previously
mentioned OnTriggerEnter2Dfunction:
using UnityEngine;
using System.Collections;
public class Pacdot : MonoBehaviour {
void OnTriggerEnter2D(Collider2D co) {
// Do Stuff...
}
}
Now this one is easy. We will check if the thing that walked over the Pac
the Pac-Dot:
using UnityEngine;
using System.Collections;
public class Pacdot : MonoBehaviour {
void OnTriggerEnter2D(Collider2D co) {
if (co.name == "pacman")
Destroy(gameObject);
}
}
Note: if we wanted to implement a highscore in our game, then this would be the place to increase it.
Now we can right click the Pac-Dot in the Hierarchy
that we always position the Pac-Dots at rounded coordinates like
Here is the result after duplicating and positioning the Pac
If we press Play then Pac-Man can now eat them:
thing that walked over the Pac-Dot was Pac-Man, and if so then we will destroy
Note: if we wanted to implement a highscore in our game, then this would be the place to increase it.
Hierarchy, select Duplicate and move it to the next free position. It's i
Dots at rounded coordinates like (1, 2) and never (1.003, 2.05)
Here is the result after duplicating and positioning the Pac-Dot over and over again:
Man can now eat them:
Man, and if so then we will destroy
Note: if we wanted to implement a highscore in our game, then this would be the place to increase it.
and move it to the next free position. It's important
(1.003, 2.05).
Feel free to also move all those Pac-Dots into
So that we can collapse the maze GameObject in order to have a clean view at the Hierarchy:
The Ghosts
A good Pac-Man clone needs some enemies, so let's add a few ghosts.
The Red Ghost Image
As usual we will begin by drawing a ghost Sprite with all the animations in it. Each row will contain one animation:
• right
• left
• up
• down
The first one will be the red ghost, also known as
.
Let's select it in the Project Area and then modify the
into the maze GameObject:
So that we can collapse the maze GameObject in order to have a clean view at the Hierarchy:
Man clone needs some enemies, so let's add a few ghosts.
usual we will begin by drawing a ghost Sprite with all the animations in it. Each row will contain one animation:
The first one will be the red ghost, also known as Blinky: It is in the sprites folder.
and then modify the Import Settings in the Inspector:
usual we will begin by drawing a ghost Sprite with all the animations in it. Each row will contain one animation:
Creating the Animations
It's important that we set the Sprite Mode to
the Sprite Editor button and slice it as a 16 x 16
Afterwards we can close the Sprite Editor and press
into the Scene, just like we did with Pac-Man.
At first we will drag Slice 0 and 1 into the Scene and save the animation as
We will repeat this process for:
• Slice 2 and 3 as left
• Slice 4 and 5 as up
• Slice 6 and 7 as down
to Multiple again because our Sprite contains several slices. Let's click
16 x 16 grid:
and press Apply. Now it's time to create the animations by dragging the slices
Man.
into the Scene and save the animation as right.anim in a new
several slices. Let's click
. Now it's time to create the animations by dragging the slices
BlinkyAnimation folder.
Cleaning up after Unity
Now we can clean up the Hierarchy again by deleting the
We can also delete the blinky_2, blinky_4 and
again by deleting the blinky_2,blinky_4 and blinky_6 GameObjects:
and blinky_6 files from theBlinkyAnimation folder in the
GameObjects:
folder in the Project Area:
The Animation State Machine
Let's double click the blinky_0 file to open the Animator:
We will create the exact same animation state machine that we used for Pac
the animations, create the Parameters and then set the Transitions:
• Any State to right with the Condition DirX > 0.1
• Any State to left with the Condition DirX <
• Any State to up with the Condition DirY > 0.1
• Any State to down with the Condition
Here is the final animation state machine in the Animator:
Renaming and Positioning Blinky
Let's make sure to keep everything nice and clean. We will select the
it to blinky:
file to open the Animator:
We will create the exact same animation state machine that we used for Pac-Man before. All we have to do is drag in
the animations, create the Parameters and then set the Transitions:
DirX > 0.1
DirX < -0.1
DirY > 0.1
DirY < -0.1
Here is the final animation state machine in the Animator:
Let's make sure to keep everything nice and clean. We will select theblinky_0 GameObject in the
Man before. All we have to do is drag in
GameObject in the Hierarchy and rename
We will also change the position in the Inspector
Ghost Physics
Alright so Blinky should be part of the Physics world again. Let's select
2D in the Inspector and assign the following properties:
Note: we enabled Is Trigger because Blinky
Blinky is also supposed to move around the maze, which means that we will need to add a
select Add Component->Physics 2D->Rigidbody 2D
Bringing Blinky to the Foreground
Just like Pac-Man, we want Blinky to be drawn in the foreground, in front of the Pac
the Order in Layervalue to 1:
Inspector so that Blinky is in the middle of the maze:
linky should be part of the Physics world again. Let's select Add Component->Physics 2D
and assign the following properties:
is a ghost, and ghosts can walk right through things.
Blinky is also supposed to move around the maze, which means that we will need to add a Rigidbody
Rigidbody 2D:
Man, we want Blinky to be drawn in the foreground, in front of the Pac-Dots. All we have to do to is set
Physics 2D->Circle Collider
is a ghost, and ghosts can walk right through things.
Rigidbody to him. Let's
Dots. All we have to do to is set
The Ghost Movement
Alright so we don't know very much about how the AI works in the original Pac-Man game, except for the fact that it's
deterministic (which is a fancy word for not-random). It also appears as some ghosts are more focused on moving
around the maze, while others are more focused on following Pac-Man, or perhaps even trying to position themselves in
front of him.
In this Tutorial we will focus on the easiest of the AI options: moving around the maze. We will create a waypoint
movement Script that makes Blinky run along a certain path. What sounds almost too simple is actually a pretty decent
solution to our AI problem. The longer and the more complex the path, the harder it is for the player to evade Blinky.
Let's select Add Component->New Script, name it GhostMove, selectCSharp and then move it into our Scripts folder.
Afterwards we can double click it so it opens:
using UnityEngine;
using System.Collections;
public class GhostMove : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
We won't need the Start or the Update function, instead we will use theFixedUpdate function (because it's meant for
physics stuff like movement):
using UnityEngine;
using System.Collections;
public class GhostMove : MonoBehaviour {
void FixedUpdate () {
}
}
Let's add a public Transform array so that we can set the waypoints in the Inspector later on:
using UnityEngine;
using System.Collections;
public class GhostMove : MonoBehaviour {
public Transform[] waypoints;
void FixedUpdate () {
}
}
Note: an array means that it's more than just one Transform.
We will also need some kind of index variable that keeps track of the waypoint that Blinky is currently walking towards:
using UnityEngine;
using System.Collections;
public class GhostMove : MonoBehaviour {
public Transform[] waypoints;
int cur = 0;
void FixedUpdate () {
}
}
Note: the current waypoint can always be accessed with waypoints[cur].
And of course a movement speed variable:
using UnityEngine;
using System.Collections;
public class GhostMove : MonoBehaviour {
public Transform[] waypoints;
int cur = 0;
public float speed = 0.3f;
void FixedUpdate () {
}
}
Now we can use the FixedUpdate function to go closer to the current waypoint, or select the next one as soon as we
reached it:
void FixedUpdate () {
// Waypoint not reached yet? then move closer
if (transform.position != waypoints[cur].position) {
Vector2 p = Vector2.MoveTowards(transform.position,
waypoints[cur].position,
speed);
GetComponent<Rigidbody2D>().MovePosition(p);
}
// Waypoint reached, select next one
else cur = (cur + 1) % waypoints.Length;
}
Note: we used the Vector2.MoveTowards function to calculate a point that is a bit closer to the waypoint. Afterwards we
set the ghost's position withrigidbody2D.MovePosition. If the waypoint is reached then we increase thecur variable by
one. We also want to reset the cur to 0 if it exceeds the list length. We could use something like if (cur ==
waypoints.Length) cur = 0, but using the modulo (%) operator makes this look a bit more elegant.
Let's not forget to set the Animation Parameters too:
void FixedUpdate () {
// Waypoint not reached yet? then move closer
if (transform.position != waypoints[cur].position) {
Vector2 p = Vector2.MoveTowards(transform
waypoints[cur].position
speed);
GetComponent<Rigidbody2D>().MovePosition
}
// Waypoint reached, select next one
else cur = (cur + 1) % waypoints.Length;
// Animation
Vector2 dir = waypoints[cur].position - transform
GetComponent<Animator>().SetFloat("DirX"
GetComponent<Animator>().SetFloat("DirY"
}
Great, there is one last thing to add to our Script. The ghosts should destroy Pac
void OnTriggerEnter2D(Collider2D co) {
if (co.name == "pacman")
Destroy(co.gameObject);
}
Note: feel free to decrease Pac-Man's lives or show a
Adding Waypoints
Alright, let's add some waypoints for Blinky
We will rename it to Blinky_Waypoint0 and then assign a
Note: a Gizmo is just a visual helper, we don't see it when playing the game
Let's also position it at (15, 20). Here is how it looks in the Scene now:
transform.position,
position,
MovePosition(p);
transform.position;
"DirX", dir.x);
"DirY", dir.y);
Great, there is one last thing to add to our Script. The ghosts should destroy Pac-Man upon colliding with him:
or show a Game Over screen at this point.
Alright, let's add some waypoints for Blinky. We will begin by selectingGameObject->Create Empty
and then assign a Gizmo to it so we can see it easier in the Scene:
Note: a Gizmo is just a visual helper, we don't see it when playing the game.
. Here is how it looks in the Scene now:
Man upon colliding with him:
Create Empty from the top menu.
to it so we can see it easier in the Scene:
Now we can duplicate the Waypoint, rename it to
Then Blinky_Waypoint2 at (10, 14):
And Blinky_Waypoint3 at (19, 14):
And finally Blinky_Waypoint3 at (19, 20):
And because our Movement Script will automatically continue to walk to the first waypoint after the last one was
reached, we will have a perfect loop.
Now we can duplicate the Waypoint, rename it to Blinky_Waypoint1and position it at (10, 20)
And because our Movement Script will automatically continue to walk to the first waypoint after the last one was
(10, 20):
And because our Movement Script will automatically continue to walk to the first waypoint after the last one was
Let's select blinky in the Hierarchy again and then drag one wayp
our GhostMove Script:
If we press Play then we can see how Blinky moves along the waypoints:
Of course, the current waypoints are rather simple. So feel free to create a more complex route like this one:
Pinky, Inky and Clyde
We don't want Blinky to feel lonely in there, so let's repeat the same work flow for
Note: it's important that we use different waypoints and movement speeds for each ghost in order to make the game
more challenging.
If we press Play then we can now play a nice round of Pac
again and then drag one waypoint after another into the Waypoints
then we can see how Blinky moves along the waypoints:
Of course, the current waypoints are rather simple. So feel free to create a more complex route like this one:
We don't want Blinky to feel lonely in there, so let's repeat the same work flow for Pinky, Inky
Note: it's important that we use different waypoints and movement speeds for each ghost in order to make the game
then we can now play a nice round of Pac-Man:
Waypoints slot of
Of course, the current waypoints are rather simple. So feel free to create a more complex route like this one:
and Clyde:
Note: it's important that we use different waypoints and movement speeds for each ghost in order to make the game