Hi, I am currently trying to improve the performance of my 3d tower defense game. The main bottleneck for now is how I move all the enemies along the path (composed of waypoints). After profiling the game, I found that the movement script, more precisely the distance calculations are a huge hit in performances (30% sometimes).
Here is the entire code for the enemy movements :
using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(Enemy))]
public class EnemyMovement : MonoBehaviour
{
private Transform target;
private int waypointIndex = 0;
public Vector3 offset;
public float rightLeftOffset;
public float turnSpeed;
private Enemy enemy;
public float percentDistanceMade;
private Waypoints waypoints;
void Start()
{
enemy = GetComponent<Enemy>();
if(enemy.isFlying)
{
waypoints = MapData.airPaths[enemy.path-1];
}
else
{
waypoints = MapData.groundPaths[enemy.path-1];
}
//second waypoint because 0 is spawn
target = waypoints.points[1];
rightLeftOffset = Random.Range(-1.7f, 1.7f);
}
void FixedUpdate()
{
Movements();
}
void Movements()
{
// TestIfCloseToOtherZombie();
//chopper la direction dans laquelle aller
Vector3 dir = target.position - ((transform.position-offset) - (rightLeftOffset*transform.right));
//déplacer l'enemy
transform.Translate(dir.normalized * enemy.speed * Time.fixedDeltaTime, Space.World);
Vector3 rotDir = new Vector3(dir.x, 0, dir.z);
if(rotDir != Vector3.zero)
{
Quaternion lookRotation = Quaternion.LookRotation(rotDir);
transform.rotation = Quaternion.Lerp(transform.rotation, lookRotation, turnSpeed * Time.fixedDeltaTime);
}
//marge d'erreur pour éviter qu'il bug dans le waypoint (+ de speed = + de marge sinon bug)
if(Vector3.Distance(((transform.position-offset) - (rightLeftOffset*transform.right)), target.position) <= enemy.wayPointPrecision)
{
GetNextWaypoint();
}
GetCurrentPosition();
}
private void GetNextWaypoint()
{
//vérifie si il y a un waypoint prochain, sinon c'est la fin du parcours
if(waypointIndex >= waypoints.points.Length -1){
EndPath();
return;
}
waypointIndex++;
target = waypoints.points[waypointIndex];
}
private void EndPath()
{
if(enemy.isBoss)
{
PlayerStats.lives = 0;
}
else
{
PlayerStats.lives--;
}
enemy.RemoveFromList();
PlayerStats.enemyThatGotIntoTown++;
Destroy(gameObject);
}
public void GetCurrentPosition()
{
float dist =0f;
for (int i = 0; i < waypointIndex-1; i++) // les waypoints précédents
{
dist += Vector3.Distance(waypoints.points[i].transform.position, waypoints.points[i+1].transform.position);
}
if(waypointIndex >= 1) //le waypoint acutel
{
dist += Vector3.Distance(waypoints.points[waypointIndex-1].transform.position, transform.position);
}
dist = (dist/waypoints.totalGroundDistance) * 100;
percentDistanceMade = dist;
}
private void OnDrawGizmos()
{
Gizmos.DrawLine(transform.position,((transform.position-offset) - (rightLeftOffset*transform.right)));
}
}
The part that consumes the most performance according to the profiler is GetCurrentPosition. The result of this function is also used by turrets to determine which enemies are the first ones to arrive (if the turret is set to attack the first for example). I don’t really know how I can improve this part of the code without loosing track of the individual position of each enemies, which is essential to the turrets.
Here is a pic of the map and the path enemies take :
Also I put all movements inside FixedUpdate because drops in fps caused the enemies to miss checkpoints and teleport but I know it is not the right thing to do…
Thanks for any help !


