Enemy movement via NavMesh
The purpose of the blog is to document my journey in building a simple Tower Defense game. In this first part I show how I made the enemy object move towards to the target using Navigation AI (NavMesh).
The following Unity packages will be covered:
- New Navigation System
- ProBuilder for level design.
- Simple and reusable C# code
Required Packages
The following packages need to be installed from the Unity Registry.
- NavMesh
- ProBuilder
Game Platform and NavMesh
Using ProBuilder I created a cube, scaled it down and used it as a platform. Then I added some custom shapes as obstacles for the enemy. For the enemy object I used a simple capsule and for the target a sphere.
Creating a NavMesh
In order to apply AI Navigation needed for the enemy object to find the way to the target, I selected the platform and added the NavMeshSurface component.
Creating an Agent
The capsule is used as enemy and for it to know its way around the NavMesh I added a Nav Mesh Agent to it.
Explain logic to move the enemy and destroy it once the Target is reached
With the NavMeshSurface and NavMeshAgent applied, the next step is to create a C# script and add it to the enemy (capsule).
Above the Start method:
- UnityEngine.AI has been added to the script since it is needed for the Navigation System
- Created private variables for the enemy, target, lastPosition and DistanceThreshold to use later in the code.
The Start method:
- Assign the target variable to the target GameObject (Sphere) and check if the GameObject is available.
- Assign the NavMeshAgent Component to the enemy(capsule).
- Tell the enemy object where it needs to go (target position)
- Assign the enemy position to the lastPosition variable. It will be used later in the FaceDirection method.
The Update method:
- Calling the two custom methods I created. DestroyOnTarget and FaceDirection.
Custom function - DestroyOnTarget:
- The purpose of this method is to destroy the enemy GameObject once it reaches the target.
- The code checks the distance between the enemy and the target. If the enemy is closer then 0.3 units (Threshold), the condition becomes true and the enemy GameObject will be destroyed.
Custom function - FaceDirection:
- Assign a new Vector3 variable Direction and assign it the current position of the enemy object.
- The if condition checks if the enemy is moving and if so, it will rotate (Z Axis is the front) the enemy to look in the direction of the movement.
The complete C# code for the enemy movement script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using UnityEngine;
using UnityEngine.AI;
public class EnemyMovement : MonoBehaviour
{
private NavMeshAgent agent;
private GameObject target;
private Vector3 lastPosition;
[SerializeField] private float ThresholdDistance = 0.3f;
void Start()
{
target = GameObject.Find("target");
if (target == null)
{
Debug.LogError("Could not find the 'target' object.");
return;
}
agent = GetComponent<NavMeshAgent>();
agent.destination = target.transform.position;
lastPosition = transform.position;
}
void Update()
{
if (agent.velocity.magnitude > 0)
{
FaceDirection();
}
DestroyOnTarget();
}
void DestroyOnTarget()
{
if (agent.remainingDistance <= ThresholdDistance)
{
Destroy(gameObject);
}
}
void FaceDirection()
{
Vector3 direction = transform.position - lastPosition;
if (direction.magnitude > 0.01f)
{
transform.LookAt(transform.position + direction);
lastPosition = transform.position;
}
}
}