[Problem] Need help with this! C#

I’m making a top-down game and the problem come when I add the bots.
I have a simple AI script to indicate the bots 3 possible targets: Normal food, player and another bots.
To recognize each of the targets, I indicated it with tags: “food”, “Player” and “bot”
It work perfect with “food” and “Player”, but when it touch with another one with the same target, it disappear.

How I can differentiate the bots with a String instead of a tag?
There is my script:

using UnityEngine;
using System.Collections;

public class bot_profile : MonoBehaviour
{
    public string Name = "botname";
    public GameObject Skin;
    public GameObject dmenu;
    public float Aggressivity;                              // Bot Difficulty (0 = easy | 1 = normal | 2 = hard)
    public float BotMoveSpeed;                              // Bot movement speed
    public static float BotCurrentMass = 10f;               // Bot mass
    public static float BotCellSize = 0.2f;
    public float BotMaxDistance;                            // Max distance to see player/bot
    public float timeleft = 20f;

    public bool Neutral = true;                             // Neutra status
    public bool Hunting = false;                            // Hunting status
    public bool Escape = false;                             // Running away status


    private Transform myTransform;

    void Start()
    {
        myTransform = transform;
    }

    void Update()
    {
        Skin.transform.localScale = new Vector3(BotCellSize, BotCellSize, BotCellSize);

        // Neutral //

        if (Neutral == true)
        {
            Debug.Log(Name + " is neutral");
            Escape = false;
            Hunting = false;

            Vector3 dir = GameObject.FindGameObjectWithTag("food").transform.position - myTransform.position;
            dir.z = 0.0f;

            myTransform.position += (GameObject.FindGameObjectWithTag("food").transform.position - myTransform.position).normalized * BotMoveSpeed * Time.deltaTime;
        }

        // Hunting //

        if (BotCurrentMass > cball.CurrentMass)
        {
            Debug.Log(Name + " is hunting");
            Escape = false;
            Hunting = true;
            Neutral = false;

            Vector3 dir = GameObject.FindGameObjectWithTag("Player").transform.position - myTransform.position;
            dir.z = 0.0f;

            Vector3 dir2 = GameObject.FindGameObjectWithTag("bot").transform.position - myTransform.position;
            dir2.z = 0.0f;

            myTransform.position += (GameObject.FindGameObjectWithTag("Player").transform.position - myTransform.position).normalized * BotMoveSpeed * Time.deltaTime;

            myTransform.position += (GameObject.FindGameObjectWithTag("bot").transform.position - myTransform.position).normalized * BotMoveSpeed * Time.deltaTime;
        }

        // Escape //

        if (cball.CurrentMass > BotCurrentMass)
        {
            Debug.Log(Name + " is running");
            Neutral = false;
            Escape = true;
            Hunting = false;

            Vector3 moveDir = transform.position - GameObject.FindGameObjectWithTag("Player").transform.position;

            Vector3 moveDir2 = transform.position - GameObject.FindGameObjectWithTag("bot").transform.position;

            transform.Translate(moveDir.normalized * BotMoveSpeed * Time.deltaTime);

            transform.Translate(moveDir2.normalized * BotMoveSpeed * Time.deltaTime);
        }

    }

    void OnTriggerEnter2D(Collider2D food)
    {
        if (food.gameObject.tag == "Player")
        {
            if (cball.CurrentMass < BotCurrentMass)
            {
                BotCellSize += cball.CellScale;
                BotCurrentMass += cball.CurrentMass;
                dmenu.SetActive(true);
                Neutral = true;
                Destroy(food.gameObject);
            }       
        }
        if (food.gameObject.tag == "food")
        {
            BotCellSize += 0.01f;
            BotCurrentMass += 1f;
            Destroy(food.gameObject);
            Neutral = true;
        }

        if (food.gameObject.tag == "bot")
        {
            BotCellSize += BotCellSize;
            BotCurrentMass += BotCurrentMass;
            Destroy(food.gameObject);
        }
    }

    void OnGUI()
    {
        GUI.Label(new Rect(10, 85, 100, 50000), "tm: " + timeleft);
    }
}

Thanks.

Um…

if(food.gameObject.tag=="bot")
{
    if(food.gameObject.GetComponent<bot_profile>().Name == "Some bot name here")
    {
        //Code here
    }
}

? Assumes another bot always has same script. Or you can make another public string tag; in that class and use .tag instead.

It seems like you’re doing too much work with “FindGameObjectWithTag”. That will only return the first object it finds in the hierarchy, and is a very expensive function. It seems like you want to find the closest one of all of them, excluding the current gameobject.

Without knowing more about your game mechanics, it’s hard to say what the best solution for you would be. Maybe something like this is more what you’re trying to do?

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class bot_profile : MonoBehaviour {
    public string Name = "botname";
    public GameObject Skin;
    public GameObject dmenu;
    public float Aggressivity;                  // Bot Difficulty (0 = easy | 1 = normal | 2 = hard)
    public float BotMoveSpeed;                  // Bot movement speed
    public static float BotCurrentMass = 10f;   // Bot mass
    public static float BotCellSize = 0.2f;
    public float BotMaxDistance;                // Max distance to see player/bot
    public float timeleft = 20f;

    public bool Neutral = true;                 // Neutra status
    public bool Hunting = false;                // Hunting status
    public bool Escape = false;                 // Running away status


    private Transform myTransform;
    private GameObject player;

    private List<GameObject> bots;
    private GameObject closestBot;

    private List<GameObject> food;
    private GameObject closestFood;

    private void Start() {
        myTransform = transform;
        // assuming there's only one player.  Otherwise do the same as bots and food
        player = GameObject.FindGameObjectWithTag("Player");

        bots = GetOtherObjectsByTag("bot");
        closestBot = GetClosestObject(bots);

        food = GetOtherObjectsByTag("food");
        closestFood = GetClosestObject(food);
    }

    // finds all gameobjects with the given tag, then removes this gameobject
    private List<GameObject> GetOtherObjectsByTag(string tag) {
        List<GameObject> others = new List<GameObject>(GameObject.FindGameObjectsWithTag(tag));

        // remove this gameobject if it's in the list
        if(others.Contains(gameObject)) {
            others.Remove(gameObject);
        }

        return others;
    }

    // finds the nearest GameObject to this one
    // expensive function, use sparingly
    private GameObject GetClosestObject(List<GameObject> list) {
        GameObject closestGameObject = null;
        float smallestDistance = float.MaxValue;

        foreach(GameObject go in list) {
            if(go != null) {
                float dist = Vector3.Distance(go.transform.position, transform.position);
                if(dist < smallestDistance) {
                    smallestDistance = dist;
                    closestGameObject = go;
                }
            }
        }

        return closestGameObject;
    }

    private void Update() {
        // If the closest one is gone, get the next closest
        if(closestBot == null) {
            closestBot = GetClosestObject(bots);
        }
        if(closestFood == null) {
            closestFood = GetClosestObject(food);
        }

        Skin.transform.localScale = new Vector3(BotCellSize, BotCellSize, BotCellSize);

        // Neutral //

        if(Neutral) {
            Debug.Log(Name + " is neutral");
            Escape = false;
            Hunting = false;
            if(closestFood != null) {
                Vector3 dir = (closestFood.transform.position - myTransform.position).normalized;
                dir.z = 0.0f;
                myTransform.position += dir * BotMoveSpeed * Time.deltaTime;
            }
        }

        // Hunting //

        if(BotCurrentMass > cball.CurrentMass) {
            Debug.Log(Name + " is hunting");
            Escape = false;
            Hunting = true;
            Neutral = false;

            Vector3 dir = (player.transform.position - myTransform.position).normalized;
            dir.z = 0.0f;
            myTransform.position += dir * BotMoveSpeed * Time.deltaTime;

            if(closestBot != null) {
                Vector3 dir2 = (closestBot.transform.position - myTransform.position).normalized;
                dir2.z = 0.0f;
                myTransform.position += dir2 * BotMoveSpeed * Time.deltaTime;
            }
        }

        // Escape //

        if(cball.CurrentMass > BotCurrentMass) {
            Debug.Log(Name + " is running");
            Neutral = false;
            Escape = true;
            Hunting = false;

            Vector3 moveDir = (transform.position - player.transform.position).normalized;

            Vector3 moveDir2 = (transform.position - closestBot.transform.position).normalized;

            transform.Translate(moveDir * BotMoveSpeed * Time.deltaTime);

            transform.Translate(moveDir2 * BotMoveSpeed * Time.deltaTime);
        }

    }

    private void OnTriggerEnter2D(Collider2D food) {
        if(food.gameObject == player) {
            if(cball.CurrentMass < BotCurrentMass) {
                BotCellSize += cball.CellScale;
                BotCurrentMass += cball.CurrentMass;
                dmenu.SetActive(true);
                Neutral = true;
                Destroy(food.gameObject);
            }
        }
        if(food.gameObject.tag == "food") {
            BotCellSize += 0.01f;
            BotCurrentMass += 1f;
            Destroy(food.gameObject);
            Neutral = true;
        }

        if(food.gameObject.tag == "bot") {
            BotCellSize += BotCellSize;
            BotCurrentMass += BotCurrentMass;
            Destroy(food.gameObject);
        }
    }

    private void OnGUI() {
        GUI.Label(new Rect(10, 85, 100, 50000), "tm: " + timeleft);
    }
}

I’m trying to make a game like agario, but with bots. This script is attached to each of the bots and the idea is to fulfill the role of a human player, so that if one of these bots is the smallest it should disappear. Thanks.

Yes. each bot has the same script. I don’t know another form to make this. Thanks for the help.

You also may benefit from using an Enum for keeping state instead of lots of booleans.

See this example class:

public enum BotState {
    Neutral,
    Escaping,
    Hunting,
}
public class Bot {
    public BotState currentState;

    private void Awake() {
        SetState(BotState.Neutral);
    }

    private void SetState(BotState newState) {
        currentState = newState;
    }
}

To add to this, GetClosestObject(List list) has a check when go is null, but if the list is empty (for whatever reason) this method returns null. Later on result of this method is used in a distance calculation, but there’s no account for the case where the value is null.

Also, since speed is mentioned in the comments. It’s probably better to have a list of Transforms instead of GameObjects, so you could also write

foreach(Transform go in list) {
            if(go != null) {
                float dist = Vector3.Distance(go.position, myTransform.position);
                if(dist < smallestDistance) {
                    smallestDistance = dist;
                    closestGameObject = go;
                }
            }
        }

and save yourself a whole bunch of (internal) GetComponent() calls.
Same goes for myTransform.position, which was already declared

You’re right about the null list case, I’ve added two null checks to prevent a null reference exception when there are no bots or food.

As for your other point, using .transform is not actually doing a GetComponent call and is the fastest way of getting the transform from a gameObject, but having a list of Transforms is still better in this case since you just want the position so you may as well start with it.

I was sure I had read that somewhere, but you’re right. There seems to be an (old) idea floating around about an internal GetComponent call, where in fact there isn’t.

Yeah I’m not entirely certain what’s happening under the hood, but probably things like .rigidbody and .renderer were deprecated for that reason, and .transform remains because it’s referenced internally when the gameObject is constructed (just a guess).