Part 1 of 5: Creating Enemy Characters using Unity 3D - Patrolling their region
Enemy characters play a very important role in any game. As a developer it is your responsibility to make them as smart as you possibly can. There are numerous AI packages available at the Unity store that can make your characters super smart.
However, for the purpose of this article we will use simple code to make the enemy behave smartly.
There are five aspects to consider in developing a smart enemy. They should:
1) Patrol their region and have some fun
2) Be self-aware and determine proximity to main player
3) Run to main player
4) Attack main player
5) Manage health & die beautifully
We will dedicate an entire blog post for each aspect of creating an enemy.
This blog post will cover enemy patrolling.
Patrol their region and have some fun
Let's create a simple project so that we can demonstrate how patrolling works.
Here are the steps:
a) Create a new Unity Project
b) Create an empty plane
> Game Object -> Create Other -> Plane
Make it large enough to cover a playable area so that the enemy can move around
c) Next let's create our enemy character
> Game Object -> Create Other -> Cylinder
Now that you have a cylinder on the screen, position it so that it is visible from your view.
d) Next create a directional light so that you can view the cylinder in the plane.
> Game Object -> Create Other -> Directional Light
This establishes the basic framework that we will use for our enemy character development.
The way patrolling works in most games is that the enemies mostly have a pre-defined path that they traverse in a loop. This keeps them looking alive and it gives them a chance to discover our player. It is also a good idea to give them some animation & audio clip so that they are fun to watch.
A pre-defined path is created by setting waypoints. Waypoints are simple GameObjects that are placed long the way, then a script is used to make the enemy rotate and move towards the next waypoint.
e) Let's start putting some waypoints. You can pick any object, even an empty gameobject would work, but since we are just learning let's use a spheres to create our waypoints, they will be easy to see from all angles.
> Game Object -> Create Other -> Sphere
Rename the sphere as "waypoint 1"
Copy the same sphere multiple times and place them around on the plane -- naming them "waypoint 2", "waypoint 3", "waypoint 4", etc.
Now you should have multiple waypoints on your screen and they are named correctly.
f) Next add a character controller component to the enemy gameobject. This will help move the enemy gameobject along the waypoint route.
> Click on Enemy > Inspector Panel
> Add Component
> Character Controller
g) Next create a new script and attach it to our enemy.
Click on Enemy -> Assets -> Create -> Javascript
This will create a new script and attach it to our enemy. Let's rename this script and call it, "Waypoints"
This script will help traverse our enemy across the various waypoints.
Let's start by creating a public variable that we will use to create an array of waypoints.
#pragma strict // The list of Waypoint you want the enemy to traverse public var waypoint : Transform[];
The waypoints array is declared as a public variable so that you can associate the actual waypoint GameObjects with the script.
Next drag each waypoint and drop it on this variable in the Inspector Panel.
Now you have all of these waypoints available to you in your javascript code.
Next we need to figure out the direction we want the player to move. This is achieved by calculating a direction vector as shown below:
var nextWayPoint : Vector3 = waypoint[currentWaypoint].position; // Keep waypoint at character's height nextWayPoint.y = transform.position.y; // Get the direction we need to move to // reach the next waypoint var moveDirection : Vector3 = nextWayPoint - transform.position;
Once you have access to the direction you should start rotating and moving the enemy towards the new waypoint location. You should use Unity's slerp functions to move and rotate slowly towards the desired waypoint.
// Now we need to do two things // 1) Start rotating in the desired direction // 2) Start moving in the desired direction // 1) Let' calculate rotation need to look at waypoint // by simply comparing the desired waypoint & current transform var rotation = Quaternion.LookRotation(nextWayPoint - transform.position); // A slerp function allow us to slowly start rotating // towards our next waypoint transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * dampingLook); // 2) Now also let's start moving towards our waypoint character.Move(moveDirection.normalized * patrolSpeed * Time.deltaTime);
Here's the complete code from the beginning:
#pragma strict // The list of Waypoint you want the enemy to traverse public var waypoint : Transform[]; // The walking speed between Waypoints public var patrolSpeed : float = 6; // Do you want to keep repeating the Waypoints public var loop : boolean = true; // How slowly to turn public var dampingLook = 4; // How long to pause at a Waypoint= 0; public var pauseDuration : float; private var curTime : float; private var currentWaypoint : int = 0; private var character : CharacterController; function Start(){ character = GetComponent(CharacterController); } function Update(){ if(currentWaypoint < waypoint.length){ patrol(); }else{ if(loop){ currentWaypoint=0; } } } function patrol(){ var nextWayPoint : Vector3 = waypoint[currentWaypoint].position; // Keep waypoint at character's height nextWayPoint.y = transform.position.y; // Get the direction we need to move to // reach the next waypoint var moveDirection : Vector3 = nextWayPoint - transform.position; if(moveDirection.magnitude < 1.5){ Debug.Log("enemy is close to nextwaypoint"); // This section of code is called only whenever the enemy // is very close to the new waypoint // so it is called once after 4-5 seconds. if (curTime == 0) // Pause over the Waypoint curTime = Time.time; if ((Time.time - curTime) >= pauseDuration){ Debug.Log("increasing waypoint"); currentWaypoint++; curTime = 0; } } else { Debug.Log("reaching in rotation " + moveDirection.magnitude); // This code gets called every time update is called // while the enemy if moving from point 1 to point 2. // so it gets called 100's of times in a few seconds // Now we need to do two things // 1) Start rotating in the desired direction // 2) Start moving in the desired direction // 1) Let' calculate rotation need to look at waypoint // by simply comparing the desired waypoint & current transform var rotation = Quaternion.LookRotation(nextWayPoint - transform.position); // A slerp function allow us to slowly start rotating // towards our next waypoint transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * dampingLook); // 2) Now also let's start moving towards our waypoint character.Move(moveDirection.normalized * patrolSpeed * Time.deltaTime); } }
The completed project for this post can be found here
Here's the completed application video.















