A deeper look at the enemies

Greetings, adventurer.

Today, we are taking a deeper look into the enemies. How they are built, how they behave and then we will take a look at the scripts.

For this post, I ‘am going to create a new enemy from scratch, while trying to reuse general scripts.

Today I will show you how to create “Ghost”, a completely new enemy that I will create as I write this. Ghost’s ability will be partly invisible. It will do damage on impact, and move to another location and attack again. A dungeon nightmare with other words.

Step 1: Manage the sprites

To begin with, we need a sprite. We have downloaded free sprites from LPC. The first thing we have to do, is slicing the sprite. The sprite is represented as a “.png” file. To slice the sprite, I highlight the sprite, select sprite mode: multiple and press “Sprite editor”. From here we have to do a little try and fail to slice the sprite correctly. Sometimes it slices automatically correct, but sometimes we have to manually try different slice sizes to find the correct one. In this case, I had to slice it manually with pixel size 40×46.

2015-11-17

Step 2: Creating animation

After the slicing, I now have 12 different pictures that represent the enemy. I now have to create animations. In total 8 animations. Four moving animations, one In each direction, and four idle animations. We also need an death animation, which is created is the same way, but it can be whatever you like. I will use a green explosion animation.

To do this, I select those pictures I want to use for an animation, right click -> create -> animation, and give it a proper name, e.g. GhostMoveLeft or GhostIdleRight.

Next, I move all of my animations to the animation folder, and create an animator controller called GhostAC.

Here we create 3 new states: idle, isWalking and isDead with transition between them as shows in the picture below. We also need to create some parameters: valueX, valueY, isWalking and isDead. We use isWaling and isDead as conditions for entering/leaving isWaling and isDead animations. After we have created the motion field, it is important to check “Loop time”, so the animation is not just played once.

That’s all for the animations, lets move over to create the physical part of the ghost.

 

Step 3: Adding the enemy to the game

In my scene I create an empty game object. I start by moving this game object closer to the player, so I can see the enemy when I start the game. But the enemy is not visible yet. First we have to add a sprite render. For the game object, we have an inspector panel to edit it. From here we add the sprite render (which is a component).  Now we just have to drag the sprite into the sprite render, and we have a visual enemy.

2015-11-17 (3).png

Step 4: Adding the animator controller

Now we have to add the Ghost animator controller that we created earlier. There is two ways of doing this. You can do it the normal way by finding “Animation” in the component list, or you can do it the easy way. You can just drag “GhostAC” into the inspector panel, and it automatically add the animation controller. Pretty easy.

Step 5: Adding box collider

Next the enemy need a box collider. This is so other objects, as the player, cannot run though the enemy.

Step 6: Adding rigidbody

Then we need to add a rigidbody, which gives the enemy physics in the game such as mass, gravity and collision.

Step 7: Scripting

Now comes the fun part. The first thing we want to add is the enemy stats script which controll the health, damage and stats. The setup for code is pretty simple.

First, you start with field variables and public variables. public variables can be changed in inspector and will be unique for each game object that uses the script. Field variables will be initialized by the constructor name Start()

</span>Animator anim;
GameObject statScaler;
GameObject player;
Scaler level;
<div>public int attackDamage;
public int health;
public bool debug;
public int damageIncrease;
public int yieldExp; <span style="font-family: Courier New;">

Field variables will be initialized by the constructor name Start()

</span>void Start () {
statScaler = GameObject.Find ("StatScaler");
player = GameObject.Find("Player");
anim = GetComponent&lt;Animator&gt; ();
level = statScaler.GetComponent&lt;Scaler&gt; ();
damageIncrease = level.GetScale ();
attackDamage += damageIncrease;
//health += damageIncrease;
yieldExp = 100;

}
Next, we have the built in function Update(), which is called for each frame. In this script we use Update() to decide is the enemy is dead or alive.
 void Update() {
if (health &lt;= 0) {
Die ();
}
}
A method for getting the enemy health
public int getHealth(){
return this.health;
}
A method to kill the enemy
public void Die() {
if(debug)
print ("dead");
health = 0;
anim.SetBool ("isDead", true);
anim.SetBool ("isWalking", false);
}
A terminate method. This is called on the last frame of the death animation to remove the game object when it is dead.
void Terminate() {
player.GetComponent&lt;PlayerStats&gt;().IncreaseCurrentExperience(yieldExp);
Destroy (gameObject);
}
A method to get the attack damage from the enemy
public int GetAttackDamage() {
return this.attackDamage;
}
And at last we have a method which is called when the enemy is attacked by the player
public void TakeDamage(int damage) {
if (debug)
print ("Taking dmg. health = " + health);
health -= damage;
}
This whole script is a prefab, which means that this script can be Applied to any enemy we decide to create in the future, or something else that need to have a health and can be killed.
Step 7b: Adding attack script
Now we need tok create a script for the enemy to attack the player. As a ghost, i think that is should move slow against the player, hit it once, and move away from the target again in another direction. Since it is a ghost, it should also be invisible from time to time. To do this, I reuse the hitAndRun script we have for the bat and extend it with some lines of code to adjust for the Ghost.
Just to be clear. I am not creating a whole new script for each enemy. I extend those we already have to be general for multiple enemies. This script already have methods for moving toward and away from the player.
For the Ghost to use hitAndRun-script, I added these lines of code.
Some variables
private bool isInvisible = false;
private float invisStart = 0;
private float invisStop = 0;
private float invisCD = 2.0f;
private float invisTime = 1.0f;
The logic. These lines of code will only apply to enemies named “Ghost”. In this way, it will not affect bat or other enemies using this script.

if (this.name.Equals ("Ghost")) {
if ((Time.time &gt; invisStop + invisCD) &amp;&amp; !isInvisible) {
GhostEnableInvisible ();
}
if ((Time.time &gt; invisStart + invisTime) &amp;&amp; isInvisible) {
GhostDisableInvisible ();
}
}

And two methods for change visibility


void GhostEnableInvisible(){
invisStart = Time.time;
isInvisible = true;
spriteRender.enabled = false;
}
void GhostDisableInvisible(){
invisStop = Time.time;
isInvisible = false;
spriteRender.enabled = true;
}

Step 8: Creating prefab

Now, the enemy is complete. The only thing left is creating a prefab of the enemy. This means that it is saved in the prefab folder  as a prefab, and can just be clicked and dragged into any scene you cant. Then you can modify og create as many copies you want out of it. Creating prefabs in Unity is very easy. Just right click -> create -> prefab, and drag the newly created enemy into it and give it a name.

 

2015-11-17 (5).png

Here is a picture of “Ghost” chasing me.

That’s all for today. Hope you enjoyed.

Best regards

P219 Development Team

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s