Physics2D.OverlapCircleAll не обнаруживает другие игровые объекты - PullRequest
0 голосов
/ 01 октября 2019

У меня есть префаб противника, который будет появляться в случайном положении несколько раз вокруг игрока. Однако иногда это может привести к тому, что один вражеский префаб перекрывает другой вражеский префаб.

Итак, я написал скрипт, который использует Physics2D.OverlapCircleAll() для обнаружения любых коллайдеров перед созданием вражеского префаба, который позволяет избежать вражеского префаба от перекрытия существующего противника. ,Моя проблема в том, что OverlapCircleAll() не обнаружил другие экземпляры префаба.

Я уже пробовал с Physics2D.OverlapBoxAll также. Если я создаю более 30 из этих «вражеских префабов» , по крайней мере один из них перекрывает другого врага

Этот код используется для обнаружения перекрытия:

public void SpawnEachEnemy(GameObject Enemy)
{
    Vector3 futurePosition = new Vector2(UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
                                UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y));
    bool correctPosition = false;
    while (!correctPosition)
    {
        Collider2D[] collider2Ds = Physics2D.OverlapCircleAll(futurePosition,0.2f);
        if (collider2Ds.Length > 0)
        {
            //re-spawning to prevent overlap
            futurePosition = new Vector2(UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
                                UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y));
        }
        else
        {
            correctPosition = true;
        }
    }

    GameObject b = Instantiate(Enemy) as GameObject;
    b.transform.position = futurePosition;
    b.transform.parent = this.transform;
}

Ответы [ 2 ]

0 голосов
/ 01 октября 2019

Луи Гарчински упомянул несколько возможностей, но одна из них не была упомянута: если все они создаются в промежутке одного кадра (предположение, основанное на комментарии о том, что SpawnEachEnemy вызывается в цикле),тогда вам может потребоваться включить Auto Sync Transforms в Настройки Physics2D :

Auto Sync Transforms enabled

Этот минимальный воспроизводимый пример при подключении к камере в новом 3D-проекте сцена должна работать так, как вы собираетесь с включенным Auto Sync Transforms, и она не сможет предотвратить наложения, когда она отключена. Возможно, это мешает вам работать:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScript : MonoBehaviour
{
    Vector3 upperLeft;
    Vector3 downRight;

    GameObject prefab;

    // Start is called before the first frame update
    void Start()
    {
        transform.position = new Vector3(0, 0, -3);
        upperLeft = new Vector3(-1, -1);
        downRight = new Vector3(1, 1);

        prefab = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        DestroyImmediate(prefab.GetComponent<SphereCollider>());
        prefab.transform.localScale = 0.4f * Vector3.one;
        prefab.AddComponent<CircleCollider2D>();

        for (int i = 0; i < 12; i++)
        {
            SpawnEachEnemy(prefab);
        }

        prefab.SetActive(false);

    }


    public void SpawnEachEnemy(GameObject Enemy)
    {
        Vector3 futurePosition;
        Collider2D[] collider2Ds;

        do { 
            futurePosition = new Vector2(
                UnityEngine.Random.Range(
                    upperLeft.x,
                    downRight.x),

                UnityEngine.Random.Range(
                    upperLeft.y, 
                    downRight.y));

            collider2Ds = Physics2D.OverlapCircleAll(futurePosition, 0.2f)
        } 
        while (collider2Ds.Length > 0)

        GameObject b = Instantiate(Enemy) as GameObject;
        b.transform.position = futurePosition;
        b.transform.parent = this.transform;
    }
}
0 голосов
/ 01 октября 2019

Сначала ваш код можно упростить до чего-то вроде этого:

public void SpawnEachEnemy(GameObject Enemy)
{
    Vector3 futurePosition;
    do
    {
        futurePosition = new Vector2(
            UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
            UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y)
        );

    } while (Physics2D.OverlapCircleAll(futurePosition,0.2f).Length > 0)

    GameObject b = Instantiate(Enemy) as GameObject;
    b.transform.position = futurePosition;
    b.transform.parent = this.transform;
}

Я бы также порекомендовал добавить счетчик безопасности в ваш цикл, чтобы избежать бесконечного цикла, если места нет.

Теперь многое может быть не так:

  • Может быть, OverlapCircle и спавн не происходят в одном месте? Хотя установка родителя не изменит мировую позицию, я все равно установлю позицию после установки родителя. Не проблема здесь.

  • Может быть, размер перекрытия слишком мал? Вы уверены, что ваши враги в радиусе 0,2 единицы? Попробуйте использовать Debug.DrawLine, чтобы нарисовать радиус отсканированного круга.

  • Может быть, ваши враги находятся в слое, не входящем в DefaultRaycastLayers? Попробуйте использовать намного больший радиус круга и добавляйте Debug.Log всякий раз, когда OverlapCircleAll действительно работает.

  • Есть несколько других возможных причин, таких как отключенные коллайдеры или слишком малые коллайдерыи т. д. Однако это должно охватывать наиболее вероятные ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...