Battlefield AI Build

Hello!

I have started working on a little project.

The idea is for a fantasy battlefield, two armies/groups of units will attack each other until one side wins. I have built this but it can lag and I don’t feel as though this is the best way to about it. The scripts rely on Colliders so you can imagine that is can start to struggle. I need to try and find away to have a less colliders dependent script to help reduce lag. Or maybe there is another part of the script that is affecting the lag. When there are many units on the map many of the units will take a few seconds to get going.

Each Unit has
An Animator
A Rigidbody
A Nav Mesh Agent
A Box Collider
A Sphere Collider
and the Basic_ai script

The Sphere collider acts as the aggro are for the unit, once an enemy unity enters this area the script gets this enemy as the Nav target.

Here is the script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class basic_ai : MonoBehaviour {

    public int hit_points;

    private float moral = 100;
    public Transform current_target;
    private GameObject[] targets_in_area;
    private int armour_rating;
    private int damage;

    private NavMeshAgent nav;
    private Animator anim;
    private GameObject enemy_spawn;

    private bool is_fighting;

    private string my_enemy;

    void Start() 
    {
        nav = gameObject.GetComponent<NavMeshAgent> ();
        anim = gameObject.GetComponent<Animator> ();

        if (this.gameObject.tag == "ally") {
            my_enemy = "enemy";
        } else {
            my_enemy = "ally";
        }

        if (this.gameObject.tag == "ally") {
            enemy_spawn = GameObject.Find ("enemy_spawn");
        } else {
            enemy_spawn = GameObject.Find ("player_spawn");
        }

        current_target = enemy_spawn.transform;
    }

    void Update()
    {
        if (hit_points < 0) {
            Destroy (gameObject);
        }
        if (is_fighting == false) {
            nav.SetDestination (current_target.position);
            anim.SetBool ("is_running", true);
        } else {
            anim.SetBool ("is_running", false);
        }
   
        RaycastHit hit;
        Ray meleeRay = new Ray (transform.position + Vector3.up, transform.forward);
        Debug.DrawRay (transform.position + Vector3.up, transform.forward * 25);
        if (Physics.Raycast (meleeRay, out hit, 25)) {
            if (hit.collider.tag == my_enemy) {
                anim.SetBool ("is_attacking_side", true);
                hit.collider.gameObject.GetComponent<basic_ai> ().hit_points -= 1;
                is_fighting = true;
            }
        } else {
            is_fighting = false;
            anim.SetBool ("is_attacking_side", false);
        }
    }

    void OnTriggerStay(Collider col) 
    {
        if (col.gameObject.tag == my_enemy) {
            current_target = col.gameObject.transform;
        }
    }
}

As you can see its very basic, but it works. I am post to ask on peoples opinion and where it can be improved.

Thank you for any insight.

CompareTag() is a lot better to use than tag or avoid using tags in the first place and have a list or simple Array with flags.
Here is another thread recently discussing how to get better performance with Triggers OnTriggerStay performance bottleneck

Thank you Pengocat for the help, I will try using that.

I have added .CompareTag it has helped the latency somewhat during the start when the AI is heading toward the enemy starting point. But during the fight the latency shoots up.

Something to do with OnTriggerStay I think.

You can use profiler to see what takes sweet time to complete.

@Bantaru I have used Unity for a long time and I didn’t even know about the Profiler until today! The OnTriggerStay was going up to 83%+ at times.

Clearly not a good approach! I need to find a new way to detect enemy units.
Maybe using an Array or list to find every unit on the map and search through thoses? That sounds more taxing on the system.

Set current_target in OnTriggerEnter and set it to null in OnTriggerExit. Also, update your physics matrix so the fewest number of layers are interacting with each other (ie - if the trigger is only meant to detect enemies then put enemies on a unique layer and have the trigger layer only interact with that layer (would also remove the need for a tag check))

@KelsoMRK Thank you for your advice! I added the changes and edited the layers the latency is good. Getting around 49% - 75% latency on the Behavior Update going up to the higher end when they start to fight.

I am guessing that may be due to the raycast, all of the if statements. But a massive improvement from earlier! I can’t imagine there is an alternative to the Raycast idea, acting as units sight.