Почему моя функция атаки уничтожает ВСЕ объекты, ВКЛЮЧАЯ злоумышленника? - PullRequest
2 голосов
/ 06 июня 2019

мы работаем над каким-то 2d проектом. У нас есть доска, которая похожа на шахматную доску (8x8), и некоторые предметы появляются сверху этой доски, как в тетрисе. Когда объект достигнет нижней части доски или каких-либо других объектов, он будет атаковать в 4 направлениях по всей доске - вверх, вниз, слева и справа.

У меня есть 3 сценария, Spawn, Obj_Controller и Personal_Attack. Сценарий Spawn прикреплен к пустому объекту spawnzone, оба сценария прикреплены к объекту, который мы порождаем. У объектов есть тег - Enemy, я использую его для обнаружения различий между объектами, на которые я хочу атаковать, и, например, Spawnzone и Bonuses (которых пока нет готовы). Надеюсь, я предоставлю достаточно информации о проекте, так что давайте посмотрим на код.

Spawn Я использую для порождения объектов в начале игры и после завершения каждой атаки

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, который я использую для перемещения объектов и вызова атаки, когда время пришло


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 - это скрипт, который пытается найти другие объекты в 4 направлениях, длина каждой атаки равна 8 ячейкам доски (каждый шаг == 1, transform.position каждого объекта == центр ячейки).


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;

    }
}

Таким образом, по какой-то причине, после того, как объект атаки уничтожает не только объект, который он может достичь своей атакой, но также уничтожает сам себя, и игра останавливается (спавн не происходит, потому что объект атакующего не может вызвать функцию возрождения, потому что он уже уничтожен. _.). Я не понимаю, какую ошибку я совершил.

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Единственный способ увидеть, когда это может произойти, - это если у вашего атакующего объекта тоже есть тег "Враг".Проверяйте теги на всех объектах.

Обновлено:

Так что, как оказалось, у вас есть злоумышленник с тегом "Враг", если он вам действительно по какой-то причине нужен,Вы можете просто исправить это следующим образом:

В ваших циклах с помощью "Destroy" вы можете добавить простую проверку, если это тот же объект:

if (enemy.tag == "Enemy" && enemy.gameObject != gameObject)
{
    Destroy(enemy.gameObject);
}
0 голосов
/ 06 июня 2019

Похоже, что ваши вражеские коллайдеры достаточно велики, чтобы они простирались до границ соседних квадратов и могли слегка перекрываться на границах.Я бы уменьшил радиус ваших вызовов OverlapCircleAll на небольшую величину (например, Mathf.Epsilon), чтобы не коснуться границ квадратов:

Collider2D[] hitTop = Physics2D.OverlapCircleAll(
        transform.position + new Vector3(0, i, 0), 
        0.5f - Mathf.Epsilon);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...