Как получить столкновения столкновений в unity2d?А что не так с этим кодом? - PullRequest
0 голосов
/ 29 января 2019

У меня есть круг готовых объектов.Я создаю их случайным образом около 50-100 раз.я добавил к ним жестких тел, и они стали передвигаться.проблема в том, что;Я хочу уничтожить группу из этих сборных, которые имеют один и тот же тег и сталкиваются друг с другом.но я не могу получить все коллайдеры из них.потому что некоторые из них сталкиваются с 2-х или 3-х сборных.как я могу получить их, не сталкиваясь с ними?

refrance изображение того, что я хочу сделать

я пытаюсьсделать это с помощью этого кода:

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

public class Colliders : MonoBehaviour {

    public List<GameObject> colliders;

    private void Start() {
        if (colliders == null)
            colliders = new List<GameObject>();

        colliders.Add(this.gameObject);
    }

    private void OnTriggerStay2D(Collider2D col) {
        if (col.gameObject.tag != this.gameObject.tag) return;  // if colliders haven't the same tag ignore
        if (colliders.Contains(col.gameObject)) return;         // if colliders already exist in the list ignore
        colliders.Add(col.gameObject);                          // add colliders to the list

        if (colliders.Count < 2) return;                        // if there aren't more than two gameobjects in the list ignore

        for (int i = 0; i < colliders.Count; i++)               // get all colliders in the list
        {
            if (colliders[i] == this.gameObject) return;        // if it is same as this gameobject ignore
            if (colliders[i] == col.gameObject) return;         // if it is same as this collider ignore

            Colliders colScript = col.gameObject.GetComponent<Colliders>();   // get the collider script attached to the colliders in the list
            List<GameObject> colColliders = colScript.colliders;            // get the list of the colliders in the list

            for (int j = 0; j < colColliders.Count; j++)
            {
                if (colliders.Contains(colColliders[j])) return;           // if colliders already exist in the list ignore
                colliders.Add(colColliders[j]);                            // add colliders to the list
            }
        }
    }

    private void OnCollisionExit2D(Collision2D col) {
        for (int i = 0; i < colliders.Count; i++)               // get all colliders in the list
        {
            if (colliders[i] == this.gameObject) return;        // if it is same as this gameobject ignore

            Colliders colScript = col.gameObject.GetComponent<Colliders>();   // get the collider script attached to the colliders in the list
            List<GameObject> colColliders = colScript.colliders;            // get the list of the colliders in the list

            for (int j = 0; j < colColliders.Count; j++)
            {
                if (!colliders.Contains(colColliders[j])) return;           // if colliders not exist in the list ignore
                colliders.Remove(colColliders[j]);                          // remove colliders from the list
            }
        }

        if (col.gameObject.tag != this.gameObject.tag) return;  // if colliders haven't the same tag ignore
        if (!colliders.Contains(col.gameObject)) return;         // if colliders not exist in the list ignore
        colliders.Remove(col.gameObject);                          // remove colliders from the list
    }
}

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Ну, вам нужно как-то переслать другие коллизии.

Например, сохранить коллизии OnCollisionEnter и удалить их OnCollisionExit.Если все объекты делают это, вы можете получить коллизии всех объектов, с которыми вы сейчас сталкиваетесь и т. Д.

Может выглядеть, например,

public class CollisionDetection : MonoBehaviour
{
    // List for storing current collisions 
    // (the references of the Collisions component of colliding objects to be exact)
    public List<CollisionDetection> collisions = new List<CollisionDetection>();

    private void OnCollisionEnter(Collision other)
    {
        // however you want to check the collisions
        if(other.tag != "XY") return;

        // Try to get the CollisionDetection component
        // Note depending on your collider setup you might
        // have to use GetComponentInChildren or GetComponentInParent instead
        var collComponent = other.gameObject.GetComponent<CollisionDetection>();

        // If no Collisions component found do nothing
        if(!collComponent) return;

        // If this Collisions component is already in the list do nothing
        if(collisions.Contains(collComponent)) return;

        // Add the reference to the list 
        collisions.Add(collComponent);


        // probably some check if you want to call destroy
        if(! .... ) return;

        // Careful this should be called only by one of the objects
        DestroyCollisions(new List<CollisionDetection>(){this});
    }

    private void OnCollisionExit(Collision other)
    {
        // however you want to check the collisions
        if(other.tag != "XY") return;

        // Try to get the CollisionDetection component
        // same as before you might have to use
        // GetComponentInChildren or GetComponentInParent
        var collComponent = other.gameObject.GetComponent<CollisionDetection>();

        // If no Collisions component found do nothing
        if(!collComponent) return;

        // If list doesn't contain the reference do nothing
        if(!collisions.Contains(collComponent)) return;

         // Remove reference from the list   
        collisions.Remove(collComponent);
    }

    // pass a parameter in order to not destroy the original callers objects to early
    public void DestroyCollisions(List<CollisionDetection> originalCallers)
    {
        // Now when you destroy objects check for other collisions recursiv
        foreach(var collision in collisions)
        {
            // Don't destroy the original callers since they will destroy themselves when done
            if(originalCallers.Contains(collision)) continue;

            // it is possible that two objects collide with the same other object
            // so they try to destroy the same object twice -> exception
            // So if one reference is null already skip
            if(!collision) continue;

            // Maybe another check? E.g. is color equal? etc
            if(! ...) continue;

            // Add to original callers to not destroy it to early
            originalCallers.Add(collision);

            // Destroy also this collision's collisions
            collision.DestroyCollisions(originalCallers);
        }

        // Finally destroy this object itself

        Destroy(this.gameObject);
    }
}

Как вы заполняете эти теги if, делаяВсе звонки безопасны и т. д. Ваша задача.

Никаких гарантий, хотя, поскольку я взломал это на своем смартфоне;), но я надеюсь, что вы поняли


Обновление

Чтобы не уничтожать объекты, а просто собрать их в списке, вы можете сделать

public List<CollisionDetection> FetchCollisions()
{
    var output = new List<CollisionDetection>();
    output.Add(this);

    // check for other collisions recursiv
    foreach(var collision in collisions)
    {

        foreach(var col in collision.FetchCollisions())
        {
            if(output.Contains(col)) continue;
            output.Add(col);
        }
    }
}
0 голосов
/ 29 января 2019

Обнаружение столкновения можно получить с помощью метода OnCollisionStay2D(Collision collisionInfo).Если вы получаете ссылку на то, с чем столкнулись, вы можете вызвать метод для объекта, на который он столкнулся, получить ссылку на то, с чем он столкнулся, и уничтожить gameObject.

Надеюсь, это поможет!

...