Can any1 help me optimize this script please?

Ok this script is fine untill i spawn around 40 enemies at that point the game becomes very laggy, when my units kill some enimes and the numbers drop to around 30 every thing is fine.

I am using Arongranberg’s A* pathfinding because im on a trial unity :(, and i have my node size set to 7 to try and decrease the number of paths.

using UnityEngine;
using System.Collections;
using Pathfinding;
using System.Collections.Generic;

public class EnemyUnit : MonoBehaviour 
{
	#region Variables
	private GameObject EnemySpawnLocations;

	private Seeker seeker;
	private CharacterController controller;
	private Path path;

	public float speed;
	public float defaultnextWaypointDistance = 3f;
	public int currentWaypoint = 0;
	private Vector3 diff;

	private bool attacking = false;
	private bool walking = false;
	public float curDistance = 100.0f;
	public float CurDistance = 100.0f;
	private GameObject[] units;
	public bool firstTarget = true;


	public float health = 100;
	private float hp;

	#endregion

	// Update and Start
	#region Update and Start
	void Start()
	{
		seeker = GetComponent<Seeker> ();
		controller = GetComponent<CharacterController> ();
	}

	void Update()
	{	
		hp = health;
		if(hp <= 0)
		{
			GameObject.Destroy(this.gameObject);
		}

		if(!walking  firstTarget)
		{
			StartCoroutine(Walk());
		} else
			if(!walking  path.vectorPath[path.vectorPath.Count - 1].z != FindClosestEnemy().transform.position.z)
		{
			StartCoroutine(Walk());
		}else
		if(!attacking  (Vector3.Distance(transform.position, FindClosestEnemy().transform.position) <= 5))
		{
			StartCoroutine(Attacking());
		}


	}
	#endregion

	//Find Closest Enemy and Attack!
	#region FindClosestEnemy


	public GameObject FindClosestEnemy()
	{
		units = GameObject.FindGameObjectsWithTag("Unit");
		GameObject closest = null;
		float distance = Mathf.Infinity;
		distance = Mathf.Infinity;
		Vector3 position = this.transform.position;
		foreach (GameObject go in units)
		{
			diff = go.transform.position - position;
			curDistance = diff.sqrMagnitude;
			if (curDistance < distance)
			{
				closest = go;
				distance = curDistance;
			} 
		}return closest;
	}

	#endregion	
	
	//Walk and Attack Numerator IEnumerator

	#region IEnumberator
	private IEnumerator Walk()
	{
		Vector3 closest = FindClosestEnemy().transform.position;
			firstTarget = false;
			walking = true;
			seeker.StartPath (transform.position, closest, OnPathComplete);
			yield return new WaitForSeconds(2.0F);
			walking = false;
	}

	private IEnumerator Attacking()
	{	
		attacking = true;
		FindClosestEnemy().transform.GetComponent<Unit>().Health -= 25;
		this.transform.FindChild("Body").animation.Play();
		yield return new WaitForSeconds(1.5F);
		attacking = false;
	}	

	#endregion

	// Pathfinding logic
	#region Path Finding and FixedUpdate

	public void OnPathComplete(Path p)
	{
		if(!p.error)
		{
			path = p;
			// reset waypoint
			currentWaypoint = 0;
		}
	}
		
	public void FixedUpdate()
	{
		if (path == null)
		return;
		
		if (currentWaypoint >= path.vectorPath.Count)
		return;
		
		// Calculate the direction of the unit
		Vector3 dir = (path.vectorPath [currentWaypoint] - transform.position).normalized;
		dir *= speed * Time.fixedDeltaTime;
		controller.SimpleMove (dir); //UNIT MOVEEES!!!
		
		transform.LookAt(new Vector3(path.vectorPath[currentWaypoint].x, transform.position.y, path.vectorPath[currentWaypoint].z));
		
		
		float nextWaypointDistance = defaultnextWaypointDistance;
		if (currentWaypoint == path.vectorPath.Count - 1)
			nextWaypointDistance = 0f;
		
		//Check if close enough to the current way point if we are progress to next waypoint
		if (Vector3.Distance (transform.position, path.vectorPath [currentWaypoint]) < nextWaypointDistance)// Defined At top
		{ 
			currentWaypoint++;
			return;
		}
		
	}
	#endregion
	
}

Isit my code? the Pathfinding or just my sucky computer with 2.3 Trip core and 4gig of ram

Any help appricated :hushed:

I guess the best way is to look at the CPU heavy functions and see if you can decrease them as these will be your bottle necks.
Not sure whether the profiler is a Pro only thing, but you could try and look at that and see what is costing you the most in terms of CPU power.

However, with a quick look, I’m sure that these bits of code can be quite costly and FindGameObjects will become exponential the more units you get:

FindGameObjectsWithTag("Unit");
transform.LookAt

Also, not sure how costly this is, but it may be worth storing that animation from loading and then just call Play() on it when needed?

this.transform.FindChild("Body").animation.Play();

thanks for the tip about profiler(think i have trail of proversion) looks like its something in the public void FixedUpdate(), its sucking up proccessor like nobody business

i commented transform.LookAt out still lags but better, guess i need to call these FixedUpdate functions in a IENumerator or something

Also - get rid of your foreach loops in favor of regular for loops. foreach allocates an enumerator which has to be garbage collected. And if you’re just comparing distance use sqrMagnitude instead of Vector3.Distance to avoid the square root operation.

thanks for replies guys, time to break my script tryin to fix it :stuck_out_tongue:

Edit Ive pinpointed it to this part of the code inside FixedUpdate()

Vector3 dir = (path.vectorPath [currentWaypoint] - transform.position).normalized;
		dir *= speed * Time.fixedDeltaTime;
		controller.SimpleMove (dir); //UNIT MOVEEES!!!
		transform.LookAt(new Vector3(path.vectorPath[currentWaypoint].x, transform.position.y, path.vectorPath[currentWaypoint].z));

Any tips for moving or calling it somewhere else in the script? :stuck_out_tongue:

Navmesh isn’t pro only, FYI.

Hmm ive set half my game up with A* now :(( is switching to NavMesh going to give a noticable difference?

I’ve heard people complain about performance with character controllers. Maybe try moving the transform yourself.

Yes it is definatly this, i have replaced

 controller.SimpleMove (dir);

for

	transform.Translate (dir*Time.deltaTime, Space.World);

Works pefectly :slight_smile:

Alternately you could just do this

transform.position += dir;

I have so much to learn :smile:

I have no idea about a performance comparrison, was just letting you know it’s free.

ok thanks, guess il just impliment the rest of these script changes and see how it goes. Seems to be fine at the moment