In this video we're going to setup the
animator controller for our enemy,
and we're also going to add some code to the
game manager to manage and move our enemies.
Let's start with the animator controller.
We're going to go to Animations - Animator Controller
and open our animator controller Enemy1.
We're going to create some transitions
from our default idle state
to our Enemy1Attack state
by right clicking on Enemy1Idle
selecting Make Transition
and clicking on Enemy1Attack.
We're also going to transition back to Enemy1Idle
once Enemy1Attack is complete.
Next we're going to set a condition
for when we want to transition from Enemy1Idle
to Enemy1Attack.
We're going to do this using a trigger parameter
as we did in the player.
In our list of parameters here let's click +
and we'll choose Trigger.
We're going to label this EnemyAttack.
And we'll add this to our list of conditions
from Enemy1Idle to Enemy1Attack.
Make sure that the transition is highlighted by clicking on it
and then we're going to click the + button
in the list of conditions.
Since there's only 1 parameter Enemy1Attack will be added.
We're also going to adjust the settings for this transition.
We're going to uncheck Has Exit Time
since we want to immediately transition
when it's time for the enemy to attack.
We'll unfold our settings,
set the transition duration to 0.
Transitioning out of Enemy1Attack
we will use Has Exit Time
and we'll set the exit time to 1
because we want to transition at the end of the animation.
We'll also set the transition duration to 0.
Next let's dock out animator
at the bottom of the screen and test the animation.
It's worth noting, because we created our animator
override controller for Enemy2
and are reusing the Enemy1 animator controller
we don't need to do this twice.
This same state machine will be used for both enemies.
Let's return to our Scripts folder
and open our Game Manager.
First, in Game Manager, we're going to declare
a public float called TurnDelay
and initialise it to 0.1 seconds.
This is how long the game is going to wait between turns.
We're also going to add to our namespace declarations
using System.Collections.Generic
We're going to do this so that we can use lists,
which we're going to use to keep track of our enemies.
Next we're going to declare a private list
of Enemy classes called enemies.
We're going to use this list enemies to keep
track of our enemies and to send them
their orders to move.
We're also going to declare a private boolean
called enemiesMoving.
With that done, in awake we're going to set
enemies to equal a new list of the type Enemy.
In InitGame we're going to clear our list of
enemies when the game starts using enemies.Clear.
We need to do this because the Game Manager will
not be reset when the level starts
and we need to clear out any enemies from the last level.
The next thing that we're going to do is declare our coroutine
called MoveEnemies.
We're going to use this to move our enemies
one at a time in sequence.
Inside our coroutine we're going to set
enemiesMoving to true.
Next we're going to yield and wait for the
amount of time set in turnDelay,
in this case 0.1 seconds.
We're also going to check if no enemies have been spawned yet,
which would be the case in the first level.
If they haven't we're going to add
an additional yield to cause our player to wait
even though there's no enemy that they're waiting for.
We're checking the length of our enemies list
using enemies.Count.
With our waiting done we're going to use a for loop
to loop through our enemies list
and issue the MoveEnemy command
to each of these enemies by calling
the MoveEnemy function in our enemy script.
As we call the MoveEnemy function
on each of the enemies in our list
we're going to wait before we call the next one
using yield, parsing in the moveTime variable
of our enemies.
Once we've finished our loop we're going to set
playersTurn to equal true
and enemiesMoving to equal false.
Now that our MoveEnemies coroutine is ready to use
we're going to call that from within update.
The first thing we're going to do in update
is we're going to check if it's the playersTurn
or enemiesMoving is already true,
meaning the enemies are already moving.
If either of those are true we're going to return
and not execute the following code.
If neither are true we're going to start
our coroutine MoveEnemies.
Next we're going to declare a public function
that returns void called AddEnemyToList.
It's going to take a parameter of the type Enemy called script
We're using AddEnemyToList to have the enemies
register themselves with the Game Manager
so that the Game Manager can issue
movement orders to them.
In AddEnemyToList we're just going to use
the Add function of our enemies list
and parse in our parameter script.
And that's all we're going to need to do for now.
Let's save our Game Manager and return to the editor.
Now that we're added the needed functionality
to the Game Manager and setup our animator controllers
we're going to make 2 small additions to our Enemy script.
Let's open it up in Monodevelop.
The first thing that we're going to do, in the start function,
is have our Enemy script add itself to
our list of enemies in Game Manager.
By adding our enemy to the list this way
the Game Manager will now be able to call the
public function we declared MoveEnemy in Enemy
Lastly for the Enemy we're going to use SetTrigger
to set the EnemyAttack trigger
in the animator controller that we setup.
Let's save our Enemy script and return to the editor.
Back in the editor, let's add our Enemy script
to our Enemy prefabs.
We're going to go to Prefabs -
shift-click to highlight the two Enemy prefabs
choose Component - Scripts - Enemy.
We'll set the blocking layer for both enemies
to Blocking Layer
and we're going to define the PlayerDamage variable separately.
Enemy1 is going to do 10 damage
and Enemy2 is going to do 20.
This allows us to have a weaker and stronger enemy type
to make the game a little more interesting
Let's play our scene and give it a test.
When we move the player we can see that the
enemy moves every other turn,
we can collect our food pickups,
if we collide with the walls we can attack them
and break them.
And so so far everything is working nicely.
We can see that the player's hit animation is
playing and that the enemy attack animation
is playing when it should.
The next step is going to be to add some
user interface elements, including title cards for the levels,
and some score text so that
the player can keep track of their
current food point total.
We'll do that in the next video.
Subtitles by the Amara.org community