Hello guys.
Welcome to the video.
Even though we can consider this project as completed, I still want to show you some things that you
could do to improve the game.
And I think making flying enemies is a great practice for your 2D development skills.
All right.
Because these things, they are pretty simple, but it takes the skill to make it simple and to make
it work as you want it.
So I offer you to sort of complete this section as well, because this is a great practice for you.
I believe that's what I think we're going to start by making very interesting flying enemy.
It's going to be enemy bat.
Let's go to graphics enemies.
Bat I'm going to take this sprites and I'm going to change pixel per unit to 16 or I already have it.
It's okay.
Now we're going to go to Asset Prefabs enemies.
We're going to take enemy mushroom and we're going to change it.
So it's going to be a bat.
Let's do prefab unpack completely.
Let's change the name to, uh, bed.
And then we want to remove the script because we need an embed script and we need animator, right.
This is what we need.
Let's go to Asset Graphics enemies.
Bat we're going to go to Sprite Renderer.
Take the idle place it over here.
Very nice.
So this is the flying enemy.
Uh, we need to adjust colliders, but we're going to do that later.
As of now, we want to go to rigid body and change body type to kinematic because we still want it to
move around, but we don't want it to use gravity or anything else.
We want to move object with the move towards functionality.
So that's why we're using it as kinematic.
Then we're going to close this.
Close this and let's go to asset scripts.
Enemies.
We're going to make.
Enemy bet.
Let's put it on the enemy.
Like that.
And, uh, we're going to take care of this later.
As of now, let's do animations and animator setup.
We're going to go to animations enemies, and over here we need to fix something on the plant.
We need to rename this to enemy.
Planned.
AC.
Okay, now let's go back to the folder.
And make a folder.
Bet we can go inside of this.
We need animator controller.
I'm going to name it as Enemy Bad AC.
We're going to drag it over here.
And now we are ready to create a bunch of animations.
We're going to go to animation Window, click create and we're going to have Anime Bed idle.
Let's go to graphics.
Enemies bed.
Let's take the idle.
Drag it here.
Sample rate 20.
Let's make another one.
Enemy.
Bad move.
We're going to take the fly.
Animation.
Drag it here.
Sample rate 20.
We also need.
Enemy bet.
Hit.
Gonna take the heat.
Drag it here.
Sample rate 20.
And we need the sealing in and sealing out.
These animations are used to make bat fly off the ceiling and then in the ceiling, but I want to name
them as.
Enemy.
But fly out.
Let's take the ceiling out.
Sample rate 20.
And this is how it looks.
So it flies off the ceiling.
And then there is one more enemy bat fly in.
You're going to take this and drag it over here.
Sample rate 20.
Fly in is going to land on the ceiling.
Very nice.
Now let's select the enemy bed and go to animator.
And over here we need to do a bit of a setup.
So we want to move from idle to move animation, but not immediately.
First we want to trigger fly out animation and fly in.
So we're going to make parameter.
Uh, is moving.
And over here we're going to transfer to fly out.
If is moving through with unchecked exit time and no transition duration.
But when we transfer to move, we want to have exit time one, transition duration zero.
Just like that.
Then we transfer from move to fly in.
With uh, is moving poles.
Transition duration zero, exit time unchecked.
Then we transfer into idle from flying.
So we moved.
We flied into the ceiling and we transfer into idle.
This is how it's going to be.
The next time should be one.
Transition duration zero.
Regarding this enemy bat hit animation, we can just transfer from any state.
With a trigger.
Heat.
Let's go here.
Make condition trigger exit time and check transition duration zero.
All right.
And let's uncheck controls it to self as well.
Very nice.
Animator is ready and let's go to the script.
Over here.
We want to inherit from the enemy.
And we want a bunch of variables.
So first of all, Bette should have the aggression range.
In this aggression range it will detect the player.
And if it detects the player then it's going to fly to the player, hit him and then fly back to original
position.
From that, we know that we need a private Vector3 original position, and we need private Vector3 destination.
No matter if flying to hit the player or be flying back to original position, we're going to use destination
for that.
Also, we want to have serialized field, private float, aggro radius.
I'm going to make it equal to seven by default, and this is going to be used to detect the player around
the bat.
Maybe let's organize it a bit with a batch details header.
And we want to have.
A boolean that would say if bet can be aggressive, let's make it public for now.
So it's easier for us to debug and be aggressive.
And also we're going to use Collider to detect the player.
So I want to make public Collider 2D target.
Very nice.
Now let's override our weak.
And inside of the awake.
We want to do original position equals to transform position and can move equals to false.
If you remember we have this boolean on enemy script over here.
Okay.
Then we need to override update because it's going to handle, um, movement and player detection.
And we want to override.
Handle animator and remove the base because animator on the enemy updates x velocity and we don't have
it on the bad enemy.
So I'm going to remove base and I'm going to override ondraw gizmos because I want to see radius of
uh, player check.
I'm going to do gizmos draw wire sphere from a transform position in aggro radius.
Okay.
So this is basic setup.
Now let's make the bet detect the player.
That's what I want to do.
First we're going to do private void handle player detection.
And then we're going to check if target is equals to null means we need to look for a target.
And we're going to do that only if we can be aggressive.
Then inside of this method I'm going to try to fill up variable of a target with a constant search of
the collider inside of the circle.
So we're going to do this physic 2D overlap circle from transform position in aggro radius on what is
player layer like that?
And this is going to be constantly called in the update.
Handle player detection.
Let's go and see this.
We just want to try this one.
First we're going to go to unity.
On the scene.
We need to fill up this variable over here.
So what is ground?
Ground?
What is player player.
And actually we don't need ground check on the bat so I think.
Actually, we can just assign it here.
It doesn't matter.
Let's just do it.
And.
Yeah.
Let's see the radius.
So it's pretty small.
I want to do bigger radius so it's easier to check I'm going to do 15 okay.
And let's place it.
Let's do 16 so it's easier for me to walk in the radius.
Okay, so now we can see that Beth can be aggressive.
We just need to check through over here.
And I'm in the game.
That can be aggressive and it has a target that is empty.
Now I'm going to walk into the area and.
It found player as a target, which is just what we need.
You can see it here.
Now we're going to go back to the script.
And once we detected the player we're going to stop detection and we're going to make it move to the
destination.
Right.
So over here if target is not equals to null and it will be done in the same frame as we did assign
target over here.
So this is just what we need.
So if we did that we're going to set destination equals to target transform position.
And we want to say that we cannot be aggressive anymore.
So it can be aggressive false.
Because we want to be aggressive.
Like you know when we detect in the player maybe this one uh better be named as can detect player.
Yeah.
And also we want to change animator parameter.
So that looks like it's flying out.
So I'm going to do anim set bool of is.
Moving to true, he's going to transfer into animation.
Now this is what we need to do to detect the player.
Now let's take care of the movement.
I'm going to go here and make handle.
Handle movement method.
Then I'm going to click Enter Generate method.
And inside of this method of course if Canmove is false we're going to return.
And now we need to set up movement.
Uh, let's do this.
First of all, we want to do flip.
So handle flip according to the destination dot x.
So it will always look on the destination point.
Then we want to take transform position and we want to move it with a vector two.
Move towards from transform position to destination with a move speed multiplied by time dot delta time
okay.
Now it's going to fly to a destination and it's going to work.
But we want to know what is going to happen when we flew close to the destination.
Right.
So we're going to do vector two.
And the distance between transform position and destination, and if it's less than 0.1, means we are
close enough to destination.
And we want to see what is the destination now.
Because if we flew to the player, then it means we can return back to original position.
If we came to original position, then it means we can become aggressive again and we can search for
player again and so on.
So we're going to do this.
If destination is equals to original position, then we're going to say uh can move false.
We want to stop the movement.
And also we can do anim set bool.
Of is moving to false.
So we're going to transfer back to idle animation.
And else if the destination was players position then we're going to do destination equals to original
position.
We're going to make it fly back to the original position.
And also just in case we want to make target equals to null, uh, like that.
Let's save this and let's see what it's going to do now okay.
Okay, so here is the bet.
I'm going to walk into the radius.
And it doesn't care.
Okay, and there is a reason I forgot to make it true by default.
Over here.
Let's do it.
It's almost flying I guess because can move.
Boolean is false.
Let's go to enemy bet and we want to make it true.
But I don't want to make it true immediately.
I want to make it true when we finish animation of line out.
Because when it does the flying out animation, it still supposed to be at one place.
So let's do private void allow movement and this will do just can move equals to true.
And let's go to animation and set trigger with this method.
We're going to take animation of the bed.
Let's find, uh, flying out.
And over here we're going to add event of enemy bed methods allow movement.
Okay, let's go back.
Let's make.
Can detect player true.
And let's go and try again.
Okay.
And it's flying to the player.
Very slow, but it's okay.
And it's going to fly to the last known position of the player, then it's going back.
Let me make it faster.
And stays in idle.
Very cool.
I've seen a bit of a glitch.
I'm going to check.
What is that later on.
As of now, we need to, uh, make reset functionality because now it cannot detect me again.
That's the problem.
Uh, let's go back to the script.
And how we want to do the reset functionality.
First of all, we want it to be in idle for a bit so it will not fly again.
Back to the player.
Some sort of cooldown for that.
We can um.
Go here and make can detect player equals to false when it flew to original destination just to reset
things once again and uh stop player detection.
And then over here in the update I'm going to do if idle timer is less than zero then can detect player
equals to true.
And we just need to set this timer once we came back to original position.
So over here I'm going to do idle timer equals to idle duration.
Okay.
And I believe this should do the job.
Yeah, this was quite fast, but this should be enough.
Let's go back.
And now that we're doing, uh, detection with the idle timer, it doesn't matter.
It is true or false.
So over here, um, because it's going to just reset itself automatically.
Okay, so we can detect the player.
I'm going to give it speed of ten.
So it's going to be faster to check offline to me trying to hit me.
Oh no.
Man.
That's what.
Man, that was aggressive.
So, uh, what was wrong there?
All right, so what is happening?
There is something very simple.
Um, over here, we are looking for target.
If target is equals to null and we can detect the player.
And that happens simply because we make target equals to null over here when we reach the destination.
That was a player.
So let's take this line of code and let's move it over here.
And this one will solve the issue.
Now.
Very good.
Let's save this.
Let's go back.
I'm going to change move speed of the bed to 15 so it flies faster and we can check stuff.
And I'm going to go into radius.
It flies there, goes back, waits.
Then when I enter again flies there.
Goes back, waits.
Okay.
Very nice.
Now I can see a bit of a glitch with the animation over there when it flies in.
That happens because we have a loop on the animations.
So let's go back to asset animations.
Enemy bat.
There is this fly in, fly out and hit and we can uncheck loop time.
Very good.
Let's go back to the script.
And now I want to add one more improvement.
I want to make some sort of a chase timer that we use to make bat follow the player for a couple of
seconds, and only after that it's going to fly to the last player's position.
So it's going to look like it's chasing the player.
It's going to be really nice I think.
So let's go over here.
Let's make.
Sterilized field.
Private float chase duration.
I'm going to make it equals to one second by default.
And I need private float.
Chase timer.
Very good.
Now let's go to the update.
Let's do a chase timer.
Minus equals time on delta time.
Okay, then we want to go.
Over here.
And we want to set chase timer equals to chase duration.
Okay.
And then.
Over here inside of the movement, we're going to do something simple.
We're going to update.
Destination according to the player's position, while chase timer is bigger than zero.
So I'm going to do.
If chase timer is bigger than zero, then destination is equals to uh, target transform position.
And let's just be sure this target.
Is not equal to null.
Okay, I want to try this.
I just got this idea and I think it's going to be really cool.
Now let's go back to bed and let's try this on.
So I'm going to, uh, change move speed to maybe eight and let me see this.
So it's flying towards the player, and then at some point it stops chasing the player and it's just
flying to the last position, as you can see.
Let me try to get closer so it's more noticeable.
Yeah, I think it's good.
Makes it better.
Maybe we could make it a bit faster by the time it's just trying to attack the player.
That could be very cool as well.
What is it?
Cancel.
And let's go to enemy bet.
Now we need a variable for default speed.
So I'm going to do private float default speed.
And I'm going to do serialize field.
Scalise field.
Private float.
Attack speed.
Okay, uh, let's go to awake and let's do.
Default speed equals to move speed.
Okay.
Very good.
And we know how this works.
So I'm going to make this as private.
We don't need to see it anymore.
Then, uh.
Over here, we're going to do else.
Uh, move speed equals to attack speed.
Like that.
And then when we, uh, resetting everything over here, I'm going to do move speed equals to default
speed like that.
Okay.
This like lots of confusing code.
Maybe.
Maybe I need to clean this up.
As of now.
This is good.
Uh, let's go and try this.
There is a tag speed.
So I'm going to make move speed as seven and attack speed as 12.
And let me see this.
So it flies faster when it tries to attack me, right?
I think I like it.
We can increase change duration.
To something like 1.5 and I'm going to keep it at that.
Now lastly, I need to be sure I can kill this.
So I'm going to give it move speed of um.
Seven over here and attack speed will be one.
So it flies flow and I have better chance to kill it while we testing this.
Now let's go and do colliders.
We just want to change animation to fly.
Like that.
And let's see.
Collider.
This is the collider for this bed.
Like that.
And this looks good to me.
Let's take the image trigger.
Let's move it here and let's do.
Something like that.
And lastly, this one has a kinematic rigid body.
Over here.
We want to change it to dynamic.
When we kill it.
So I'm going to go back.
The enemy script.
We're going to find die method over here.
And we're going to do something very simple if is kinematic.
RB is kinematic, then RB is kinematic false.
Okay, let me go ahead and try to kill it and be done with this video.
Few.
It could fall faster.
And also, we need to stop the movement.
Um.
So I'm going to go to Enemy Bet.
I'm going to override die method override die.
And we're going to do can move equals false.
Don't we do it on like in here.
We do not.
Okay.
It's fine.
Now let's stop the movement here so it will not try to fly back.
And I think.
The gravity scale should be okay.
Let me check other enemies.
One one.
Everybody, like most of the enemies, have an, uh, gravity scale of one.
So it should be good.
Let me try again.
How am I so bad at this game?
Okay, Hugh.
Yeah.
Cute.
Love it.
Uh, now, let's make move speed over here.
Uh.
Let's try.
Let's try nine and attack speed.
Let's try 12, which is duration 1.5.
So I'm going to keep it as it is.
I'm going to go to a prefab folder with enemies and make it as a prefab.
And we're good.
Let's go to the next video.