- Home /
Attacking more than one enemy with same tag, but unity only allows one enemy at a time?
Hi, this problem has been stressing me all night and any help is appreciated. I am using c#. I have two types of enemies, enemy1 and enemy2.
I created an enemy code and an attack code. basically it works fine for one on one situation. But if i say, use ctrl-d and make more of the same enemy, problems occur.
Firstly , i can fight many, but as soon as one dies, I cannot kill the other. ('missing game object' shows up). I target those with enemy1 and enemy2 tag. If either enemy dies, I cannot kill the other.
Secondly if I add many enemies, with same tags. So in this example, i spawn 3 guys, all with enemy1 tag. It seems i cannot kill them in any order I want.
I understand my problem is similar to:
http://answers.unity3d.com/questions/328022/i-need-help-to-attack-various-enemies-with-the-sam.html
but I wasnt unable to convert the javascript to c#.
From my understanding, my code only allows me to select two enemies to fight. If i make them chose from tags, they will randomly chose enemies with my selected tag.(So if i spawn 3 guys with enemy1 tags, unity chooses one of them at random to be my opponent and the other two are untouchable)
I do believe my code would need perhaps some array style fix but I am absolutely lose. Below is the attack code.
using UnityEngine;
using System.Collections;
public class atkm1 : MonoBehaviour {
public GameObject target;
public GameObject target1;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
attackTimer = 0;
coolDown =0.0f;
}
// Update is called once per frame
void Update () {
GameObject go = GameObject.FindGameObjectWithTag("enemy1");
target = go;
GameObject go1 = GameObject.FindGameObjectWithTag("enemy2");
target = go1;
if(attackTimer > 0)
attackTimer -= Time.deltaTime;
if(attackTimer < 0)
attackTimer = 0;
if(Input.GetKeyUp(KeyCode.F)) {
if(attackTimer == 0) {
Attack();
attackTimer = coolDown;
}
}
}
private void Attack() {
float distance = Vector3.Distance(target.transform.position, transform.position);
float distance1 = Vector3.Distance(target1.transform.position, transform.position);
//calculate damage for enemy1 tag
if(distance < 2.5f) {
hpP eh = (hpP)target.GetComponent("hpP");
eh.AddjustCurrentHealth(-10);
}
//calculate damage for enemy2 tag
if(distance1 < 2.5f) {
hpL eh = (hpL)target1.GetComponent("hpL");
eh.AddjustCurrentHealth(-10);
}
}
}
One last thing, I use public so i can 'drag and drop' the enemy objects in for testing purposes. Ofcourse even if i do that, i get the same failed results. Basically, the moment i kill one off, then i get the missing gameobject error and my player is unable to attack. EG. target:enemy1 target1:enemy2
if i kill enemy1,
target:missing object target1:enemy2
any help is muchly appreciated. Basically I have a prefab for an enemy that works and attack scripts that works. I wish to fight more than one enemy with same tag in any order .
Hmm, at the begining of your update, you set " target = go;" then "target = go1;" should it not be "target1 = go1;" ?
Answer by Jessespike · Oct 28, 2012 at 05:57 PM
Instead of a single GameObject per enemy, I replaced it with a List. You can still drag-and-drop enemies into the component like before for testing. Code not tested, but it shows Lists and arrays a bit.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class atkm1 : MonoBehaviour {
public List<GameObject> targets;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
attackTimer = 0;
coolDown =0.0f;
GameObject[] enemyTargets = GameObject.FindGameObjectsWithTag("enemy1");
if (enemyTargets != null)
{
foreach(GameObject go in enemyTargets)
{
targets.Add(go);
}
}
GameObject[] moreTargets = GameObject.FindGameObjectsWithTag("enemy2");
if (moreTargets != null)
{
foreach(GameObject go in moreTargets)
{
targets.Add(go);
}
}
}
// Update is called once per frame
void Update () {
if(attackTimer > 0)
attackTimer -= Time.deltaTime;
if(attackTimer < 0)
attackTimer = 0;
if(Input.GetKeyUp(KeyCode.F)) {
if(attackTimer == 0) {
Attack();
attackTimer = coolDown;
}
}
}
private void Attack()
{
float distance = float.MaxValue;
if (targets == null) return;
foreach (GameObject target in targets)
{
if (target != null)
{
distance = Vector3.Distance(target.transform.position, transform.position);
if (distance < 2.5f)
{
hpP eh = (hpP)target.GetComponent("hpP");
if (eh != null)
{
eh.AddjustCurrentHealth(-10);
}
hpL eh2 = (hpL)target.GetComponent("hpL");
if (eh2 != null)
{
eh2.AddjustCurrentHealth(-10);
}
}
}
}
}
}
i wrote your some code but. when i kill one enemy, then all enemies dying. what can i do?
Answer by farooqaaa · Oct 28, 2012 at 05:43 PM
Edit: I forgot that you want to attack multiple targets. For that you will need to make the target variable a generic list (means a dynamic array) and then check every target in the array inside the Attack Function:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class atkm1 : MonoBehaviour {
public List<GameObject> targets;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
target = new List<GameObject>();
attackTimer = 0;
coolDown =0.0f;
}
// Update is called once per frame
void Update () {
GameObject go = GameObject.FindGameObjectWithTag("enemy1");
GameObject go1 = GameObject.FindGameObjectWithTag("enemy2");
if(go != null)
targets.Add(go);
if(go1 != null)
targets.Add(go1);
if(attackTimer > 0)
attackTimer -= Time.deltaTime;
if(attackTimer < 0)
attackTimer = 0;
if(Input.GetKeyUp(KeyCode.F)) {
if(attackTimer == 0) {
Attack();
attackTimer = coolDown;
}
}
}
private void Attack() {
foreach(GameObject target in targets)
{
float distance = Vector3.Distance(target.transform.position, transform.position);
float distance1 = Vector3.Distance(target1.transform.position, transform.position);
//calculate damage for enemy1 tag
if(distance < 2.5f) {
hpP eh = (hpP)target.GetComponent("hpP");
eh.AddjustCurrentHealth(-10);
}
//calculate damage for enemy2 tag
if(distance1 < 2.5f) {
hpL eh = (hpL)target1.GetComponent("hpL");
eh.AddjustCurrentHealth(-10);
}
}
}
}
GameObject.FindGameObjectWithTag() method will not always return a GameObject because sometimes there are no objects found with the given tag. You need to make sure it's not null before assigning it.
GameObject go = GameObject.FindGameObjectWithTag("enemy1");
// Assign go to target only if it's not null
if(go != null)
target = go;
GameObject go1 = GameObject.FindGameObjectWithTag("enemy2");
// Assign go1 to target only if it's not null
if(go1 != null)
target = go1;
Also, in your Attack() function you need to check if target is not null before doing anything:
private void Attack() {
// If target is null then all the code will not be executed
if(target == null)
return;
float distance = Vector3.Distance(target.transform.position, transform.position);
float distance1 = Vector3.Distance(target1.transform.position, transform.position);
//calculate damage for enemy1 tag
if(distance < 2.5f) {
hpP eh = (hpP)target.GetComponent("hpP");
eh.AddjustCurrentHealth(-10);
}
//calculate damage for enemy2 tag
if(distance1 < 2.5f) {
hpL eh = (hpL)target1.GetComponent("hpL");
eh.AddjustCurrentHealth(-10);
}
}
thanks for the fast responses! I have elected to use jessepike's code for now as it has been working well thus far.