[Fixed]OnTriggerEnter Multiple Object Detection

Helllo community,

I’m not any pro with coding but I’ve made some progress with this project I’ve made.

To sum it up, right now I’m having an issue where my “border” detects a single tagged “Ally” unit and a single tagged “Enemy” unit, but when I introduce duplicates to the scene, the duplicates seem to have no effect on the “borders”. All the borders do right now is change colors depending on if they detect tagged units in a list that the OnTriggerEnter is supposed to add gameobjects to. My next guess was to make the gameObjects null after they have been added to the list from the OnTriggerEnter, but visual studio doesn’t like that.

Here is the code, only 2 scripts are in my project:

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

public class borderControl : MonoBehaviour
{

    public bool isInvaded;
    public bool isControlled;
    public bool wasAlly;
    public bool wasEnemy;
    public bool wasNeutral;

    private borderColorChange bcc;

    public List<GameObject> unitsInBorderCheck = new List<GameObject>();
    // Start is called before the first frame update
    void Start()
    {
        bcc = this.gameObject.GetComponentInParent<borderColorChange>();
    }

    // Update is called once per frame
    void Update()
    {
        CheckControl();
        if (isControlled)
        {
            isInvaded = false;
        }
        else
        {
            isInvaded = true;
        }
    }
   
    public void CheckControl()
    {
        if (unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Ally")) && !unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Enemy")))
        {
            bcc.isEnemy = false;
            bcc.isNeutral = false;
            bcc.isAlly = true;
            isControlled = true;
        }
        else if (unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Enemy")) && !unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Ally")))
        {
            bcc.isAlly = false;
            bcc.isNeutral = false;
            bcc.isEnemy = true;
            isControlled = true;
        }
        else if (unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Ally")) && unitsInBorderCheck.Contains(GameObject.FindGameObjectWithTag("Enemy")))
        {
            bcc.isEnemy = true;
            bcc.isNeutral = false;
            bcc.isAlly = true;
            isControlled = false;
           
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Ally") || other.gameObject.CompareTag("Enemy"))
        {
            unitsInBorderCheck.Add(other.gameObject);
        }
    }
    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.CompareTag("Ally") || other.gameObject.CompareTag("Enemy"))
        {
            unitsInBorderCheck.Remove(other.gameObject);
        }
    }
}

The above code was attached to a box collider which was a child of the border, it is set to “Is Trigger” and this box collider is basically occupying the space that the border owns. I also believe that this code above contains the source of my error but I will include the second script below.

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


//[ExecuteInEditMode]
public class borderColorChange : MonoBehaviour
{
    private borderControl bordcon;

    public float borderFlash = 2f;
    private float pingPongTime;

    public bool isNeutral;
    public bool isAlly;
    public bool isEnemy;

    public Material[] alliedColors;
    public GameObject[] borders;
    public List<GameObject> borderlist = new List<GameObject>();
    private MeshRenderer indMatVar;
    // Start is called before the first frame update
    void Start()
    {
        bordcon = GetComponentInChildren<borderControl>();
        GetBorders();
    }

    // Update is called once per frame
    void Update()
    {
        pingPongTime = Mathf.PingPong(Time.time, borderFlash);
        BorderColorControl();
    }
    void GetBorders()
    {
        foreach (Transform border in transform)
        {
            borderlist.Add(border.gameObject);
            borders = borderlist.ToArray();
        }
    }
    void BorderColorControl()
    {
        for (int i = 1; i < borders.Length; i++)
        {
            indMatVar = borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>();
            if (!isAlly && !isEnemy)
            {
                borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material = new Material(alliedColors[0]); //First It finds the amount of borders, then it subtracts 1 for the correct order in the array, then it finds the mesh renderer and changes the component's material
            }
            else if (isAlly && !isEnemy)
            {
                bordcon.wasNeutral = false;
                bordcon.wasEnemy = false;
                bordcon.wasAlly = true;
                borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material = new Material(alliedColors[1]);
            }
            else if (isEnemy && !isAlly)
            {
                bordcon.wasNeutral = false;
                bordcon.wasAlly = false;
                bordcon.wasEnemy = true;
                borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material = new Material(alliedColors[2]);
            }
            else if (isEnemy && isAlly)
            {
                if (bordcon.wasAlly) {
                    if (i % 2 == 0) //if i is divisible by 2
                    {
                        borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material = new Material(alliedColors[1]);
                    }
                    else
                    {
                        borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material.Lerp(alliedColors[1], alliedColors[4], pingPongTime);
                    }
                }
                else if(bordcon.wasEnemy)
                {
                    if (i % 2 == 0) //if i is divisible by 2
                    {
                        borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material = new Material(alliedColors[2]);
                    }
                    else
                    {
                        borders[borderlist.Count - i].transform.GetComponent<MeshRenderer>().material.Lerp(alliedColors[2], alliedColors[3], pingPongTime);
                    }
                }
            }
        }
    }
}

If anyone wants, I can try to explain by attaching pictures of my misworking and desired effects in the scene

If you don’t need every gameobject on the border colorcontrol side, I would do a major simplification. One way to go about it is this:

Every border segment has two integers:

int alliesInHere = 0;
int enemiesInHere = 0;

Directly in the ObTriggerEnter and in the OnTriggerExit just check if the “invading” object has the “ally” tag or the “enemy” tag like you do now. But instead of adding the gameobject, you just increase (Enter) or decrease (Exit) the corresponding (alliesInHere and enemiesInHere) integers. You can make double check that these aren’t going into negative.
And then when you do the colorization, you just check: if alliesInHere > 0 → there are allies, if enemiesInHere > 0 there are enemies, if alliesInHere + enemiesInHere = 0, no one is here, if one is bigger then you know which “army” is bigger.

1 Like

You responded very quickly, thanks, that seems to make more sense than what I was doing. I will update this thread once I have tried this.

This completely fixed my issue, it’s unbelievable! Thanks for the fix, it worked so well.

1 Like