YakutD
YakutD

Reputation: 75

Why my attack function destroy ALL objects INCLUDE attacker?

we are working at some 2d project. We got a board, which look like chess board (8x8), and some objects spawns on top beyond this board, like in tetris. When object reach bottom of board or some other objects, it will attack in 4 direction on all board - up,down,lef and right.

I have 3 scripts, Spawn, Obj_Controller, and Personal_Attack. Spawn script attached to spawnzone empty object, both of different scripts attached to objet we spawn.Objects have tag - Enemy, I use it to detect difference between objects I need attack, and, for example, Spawnzone, and Bonuses (which still is not ready). Hope I provide enough information about project, so lets see at code.

Spawn I use for spawning objects in start of the game and after end of each attack

public class Spawn : MonoBehaviour
{
    public GameObject[] objects;
    Vector3 spotSpawn;
    // Start is called before the first frame update
    void Start()
    {
        spotSpawn = transform.position;
        //Debug.Log(spotSpawn);
        NewSpawn();
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void NewSpawn()
    {

        int random_key = Random.Range(0,objects.Length - 1);
        Instantiate(objects[random_key], spotSpawn, Quaternion.identity);
    }
}

Obj_Controller I use for make objects move, and call attack when time has came


public class Obj_Controller : MonoBehaviour
{
    public float speed; // speed (I still dont use this var)

    [HideInInspector] public bool isMoved = true;   // movement flag
    [HideInInspector] public bool canSpawn = false; // spawn flag
    [HideInInspector] public bool attack = false; // attack flag

    bool LetFall = true; // falling flag

    [HideInInspector] public Animator anim; 


    // Start is called before the first frame update
    void Start()
    {

    }

    private void OnEnable()
    {
        anim = GetComponent<Animator>();
        //Debug.Log(transform.position);
    }



    // Update is called once per frame
    void Update()
    {
        if (isMoved == true && canSpawn == false)
        {
            Collider2D[] hitDown = Physics2D.OverlapCircleAll(transform.position - new Vector3(0, 1, 0), 0.5f);
            Collider2D[] hitLeft = Physics2D.OverlapCircleAll(transform.position - new Vector3(1, 0, 0), 0.5f);
            Collider2D[] hitRight = Physics2D.OverlapCircleAll(transform.position + new Vector3(1, 0, 0), 0.5f);


            if (hitDown.Length == 0)
            {
                //Check object can movew down in 1 cell
                if (LetFall == true)
                {
                    LetFall = false;
                    StartCoroutine(Down());
                }

                //Check object can move in  left or right side
                if (Input.GetKeyDown(KeyCode.LeftArrow) && hitLeft.Length == 0)
                {
                    transform.position -= new Vector3(1,0,0);
                }
                else if (Input.GetKeyDown(KeyCode.RightArrow) && hitRight.Length == 0)
                {
                    transform.position += new Vector3(1, 0, 0);
                }

            }
            else 
            {
                //Debug.Log(hitDown[0].name);
                isMoved = false;
                if(attack == false)
                {
                    attack = true;
                    gameObject.SendMessage("Attack");
                }

            }
        }
        else if(canSpawn == true)
        {
            canSpawn = false;
            GameObject spawner = GameObject.Find("SpawnZone");
            Spawn spawn = spawner.GetComponent<Spawn>();
            spawn.NewSpawn();
        }
        else
        {
            //Here will some functions, but later
        }
    }

    IEnumerator Down()
    {
        transform.position -= new Vector3(0,1, 0);
        yield return new WaitForSeconds(0.5f);
        LetFall = true;
    }

}

Personal_Attack is script which try to find other objects in 4 directions, length of each attack is equal to 8 cells of board (each step == 1, transform.position of every objects == center of cell).


public class Personal_Attack : MonoBehaviour
{

    Obj_Controller objcontroller;
    // Start is called before the first frame update
    void OnEnable()
    {
        objcontroller = GetComponent<Obj_Controller>();
    }

    // Update is called once per frame
    void Update()
    {

    }


    void Attack()
    {

        //Attack up
        for (int i = 1; i < 9; i++)
        {
            Collider2D[] hitTop = Physics2D.OverlapCircleAll(transform.position + new Vector3(0, i, 0), 0.5f);
            foreach (Collider2D enemy in hitTop)
            {
                if (enemy.tag == "Enemy")
                {
                    Debug.Log(enemy.transform.position);
                    Destroy(enemy.gameObject);
                }
            }
        }
        //Attack down
        for (int i = 1; i < 9; i++)
        {
            Collider2D[] hitDown = Physics2D.OverlapCircleAll(transform.position - new Vector3(0, i, 0), 0.5f);
            foreach (Collider2D enemy in hitDown)
            {
                if (enemy.tag == "Enemy")
                {
                    Destroy(enemy.gameObject);
                }
            }
        }
        //Attack left
        for (int i = 1; i < 9; i++)
        {
            Collider2D[] hitLeft = Physics2D.OverlapCircleAll(transform.position - new Vector3(i, 0, 0), 0.5f);
            foreach (Collider2D enemy in hitLeft)
            {
                if (enemy.tag == "Enemy")
                {
                    Destroy(enemy.gameObject);
                }
            }
        }
        //Attack right
        for (int i = 1; i < 9; i++)
        {
            Collider2D[] hitRight = Physics2D.OverlapCircleAll(transform.position + new Vector3(i, 0, 0), 0.5f);
            foreach (Collider2D enemy in hitRight)
            {
                if (enemy.tag == "Enemy")
                {
                    Destroy(enemy.gameObject);
                }
            }
        }

        objcontroller.canSpawn = true;

    }
}

So, for some reason, after attack object destroy not only object it could reach by its attack, but is destroy itself too, and game stopped (no spawn occure, because attacker object cant call spawn function, because it already destroyed ._. ). I dont understand what mistake I did.

Upvotes: 2

Views: 102

Answers (2)

Dest
Dest

Reputation: 459

The only way I see when it can happen is if your attacker object have the "Enemy" tag too. Check tags on all objects.

Updated:

So as it appeared that you have "Enemy" tag on attacker, if you really for some reason need it there, you can simply fix it this way:

In your loops with "Destroy" you can add the simple check is it the same object:

if (enemy.tag == "Enemy" && enemy.gameObject != gameObject)
{
    Destroy(enemy.gameObject);
}

Upvotes: 1

Ruzihm
Ruzihm

Reputation: 20249

It looks like your Enemy colliders are big enough that they extend to the bounds of the adjacent squares, and may overlap slightly at the boundaries. I would shrink the radius of your OverlapCircleAll calls by a small amount (such as Mathf.Epsilon) so that the boundaries of the squares are not touched:

Collider2D[] hitTop = Physics2D.OverlapCircleAll(
        transform.position + new Vector3(0, i, 0), 
        0.5f - Mathf.Epsilon);

Upvotes: 0

Related Questions