Optimizing enemy AI and a question about speed differences between C# and Javascript

Heys guys!
I am working on a doom-eque style game, and I have a few turrets scattered throughout the level.
After adding more turrets around the map, bringing the total to seven, I found to my dismay
that my fps dropped from 120 with two turrets to just bellow 40.

The turret prefab is set up as follows:

--botGameObject
----Turret - Model and Collider, with script attached.
------Turret Spitfire - Spawn point for projectiles.
------Turret Spot - Shadow enabled light.

Here is the code:

using UnityEngine;
using System.Collections;

public class BotWall : MonoBehaviour {

private Transform trget;
private Transform meTransform;
public int maxSeeDistance;
private GameObject alarmLight;
public int rotationSpeed;
private Transform botBullet;
private Transform botSpitfire;
public Transform bulletModel;
public int botBulletSpeed;
public int botBulletInterval;
public int wallBotHealth;

private int bulletTime;
	
void Awake () {
	
}
// Use this for initialization
void Start () {
	meTransform = transform;
	GameObject go = GameObject.FindGameObjectWithTag("Player");
	trget = go.transform;
	transform.Find("wallBot_spot").light.intensity = 0;
	botSpitfire = transform.Find("wallBot_spitfire");
}

void OnTriggerEnter (Collider coll)
{
if(coll.tag == "Bullets") {
	wallBotHealth --;
	Debug.Log("Wall bot health: " +wallBotHealth);
	if (wallBotHealth <= 0)
	{
		Destroy(gameObject);
	}
}

}

// Update is called once per frame
void Update () {
	//also check if object rotation doesnt intersect walls of device
	if ((Vector3.Distance(trget.position, meTransform.position)) < maxSeeDistance && !Physics.Linecast(meTransform.position, trget.position))
	{
		//Debug.Log("Clear line of sight");
		meTransform.rotation = Quaternion.Slerp(meTransform.rotation, Quaternion.LookRotation(trget.position - meTransform.position), rotationSpeed * Time.deltaTime);
		bulletTime ++;
		//bullet counter
		if (bulletTime > botBulletInterval)
		{
			Transform botBullet=(Transform)Instantiate(bulletModel, botSpitfire.position, Quaternion.identity);
			botBullet.rigidbody.AddForce(transform.forward*botBulletSpeed + new Vector3(0f,Random.Range(-15, 15),Random.Range(-15, 15)));
				
			//reset counter
			bulletTime = 0;
		}
	}
}

}

My main concern lies in optimization, any ideas? Another thing I wanted to ask is whether
there is a discernable difference between Javascript and C# in Unity games(Dont think so but worth an ask heh). Thanks a lot guys!

Ow, if anyone could let me know why my spotlight isn’t working it would be terrific!

There are a lot of small optimizing gems hidden around on the unity forums and the unity script wiki and the like:

IPhone Optimizing Scripts

General Performance Tips

And judging from your script there;

  1. You need to stop using “transform.Find” immediately. Its a VERY resource heavy method. Work around the issue by having the “wallBot_spot” gameObject as a public variable in your script.

  2. Doing meTransform = transform; in the Start method is good for optimizing, so you are doing that part right.

  3. Declare “Bullets” as a const string in your script somewhere instead of recreating the string every time OnTriggerEnter happens (wont really save you that much, but while you are optimizing… you should ;)).

  4. Remove all Debug. functions, logging writes to disk and slugs down any machine.

  5. Use the Physics. methods sparsely, they are usually very costly.

  6. Last thing; when you spawn bullets. Are the bullets always destroyed after a set time? (This is probably what is slowing everything down). Just try to play for a few minutes in the editor and then click pause and check if there are a million bullets in your scene. If it is, you should probably attach a script to your bullet prefab that destroys the bullet after some seconds.

Also on the topic of c# vs javascript, the only performance difference is when you dont use explicit types in javascript, then javascript is a little slower (miniscule, or so I’ve heard). And you can avoid this by not using the “var” everywhere, but actually using the real Type of the variables.

public class SelfDestruct : MonoBehaviour
{
    public float selfDestructTime = -1.0f;

    public void Start()
    {
        if (selfDestructTime >= 0)
        {
            Destroy(gameObject, selfDestructTime);
        }
    }
}

Hope this helps you in your optimizing :slight_smile:

The most important thing to do when optimizing is to profile your code. If you have Unity Pro you can use Unity’s in built profiler which is really easy to use. If you do not have Pro then there are still methods of profiling. There is nothing worse than blindly optimizing, in most cases the performance increase will be negligable and it will make your code less readable and harder to maintain.

The quickest way to get results is to remove code. If you comment out a line of code and it speeds up your game a lot, then that is the line that is slowing you down.


At a glance it appears this line is the biggest issue:

if ((Vector3.Distance(trget.position, meTransform.position)) < maxSeeDistance 
    && !Physics.Linecast(meTransform.position, trget.position))

Vector3.Distance will perform a square root which you don’t need. The formula for distance is:
d = sqrt(xx + yy + z*z)

if the only thing you do with that value is compare it you can remove the square root, consider this:

sqrt(x*x + y*y + z*z) < maxSeeDistance

is the same as

(x*x + y*y + z*z) < (maxSeeDistance * maxSeeDistance)

That is a lot cheaper. You can store (maxSeeDistance * maxSeeDistance) in a variable and save even more:

(x*x + y*y + z*z) < maxSeeDistanceSqrd

The code change would look something like this:

(trget.position - meTransform.position).sqrMagnitude < maxSeeDistanceSqrd

The other expensive function
Physics.Linecast(meTransform.position, trget.position)

I guess this is a line of sight test, if so it would probably be reasonable to time slice it not do it every frame. So maybe only 5 times per second do a line of sight test that would reduce the load considerably.