How to target objects without using "FindObject(s)withTag"?

Example:

In the same scene you have an Enemy, The Player, The Player’s companion, and some townfolk.

How do you get the enemy to attack everything except its own race? Mind you, there are different races involved so I can’t just tag everything with “human”.

Since there are multiple races, how do you make it so that the enemy attacks everything that might get to close?

Edit: I can’t make everything “attackable” because then it will attack other creatures of the same race, since after all, they are also “attackable” (but only by other races).

Specific example: “Johnny 1” is a player that belongs to “JohnnyRace”. “Melanie 1” is an NPC that belongs to “MelanieRace”. Thus is the same for “Adam 1”, and “Peter 1”.

Melanie 1, Adam 1, and Peter 1 are all in a house. Johhny 1 comes in along with another companion from JohnnyRace. How can I make it so that Johnny 1 attacks everyone but the character he’s with. Also, Melanie 1, Adam 1, and Peter 1 also need to be able to attack everything from another race as well, unless they are “allies” for whatever the reason.

FindObject(s)withTag is limiting, because it will only find objects with that one tag. Unless I run 10 different FindObjectwithTag scripts which would be ridiculous.

Create a script that will have an enum of all races, then define each of its own and a method to check for attack or a simple comparison.

public enum Race{None, Johnny, Melanie,Adam, Peter}

public class Test:MonoBehaviour{
    public Race race;
    void Start(){
       if(race == Race.None)Debug.LogError("No race given on " + gameObject.Name);
    }
    public bool CheckForAttack(GameObject go){
         Test test = go.GetComponent<Test>(); 
         if( test == null) return false; // Not anything to attack probably wrong though
         if(test.race != this.race) return true; // Different type
         return true;
    }

}

One object can check via collision for instance if the other is to be attacked.

void OnTriggerEnter(Collider col){
    if(col.tag != "Human") return;
    bool attack = CheckForAttack(col.gameObject); 
    if(attack) // Set the attack
}

This is considering you would have a circle collider around the human or you can use some distance checking with all human

foreach(GameObject o in allHuman){
    if(Vector3.Distance(o.transform.position, transform.position) > range) continue;
    bool attack = CheckForAttack(col.gameObject); 
    if(attack) // Set the attack
}

Without more information on the nature and criteria for attacking, it is difficult to give you a concrete answer. As a general approach, you can can tag everything that can be attacked with the same tag, something like ‘Attackable’. Then you can encode the race in another way. You could use the name of the game object or you could put the race in public variable in a component attached to every object that can be attacked.