如何在unity2d中获得碰撞的碰撞?这段代码有什么问题?

时间:2019-01-29 01:51:45

标签: unity3d collision-detection collision

我有圆形的游戏对象预制件。我随机实例化它们大约50-100次。我给它们添加了刚体,它们四处移动。问题是;我想销毁一组具有相同标签并相互碰撞的预制件。但我无法得到所有的对撞机。因为其中一些与第二或第三预制件发生碰撞。我怎样才能不碰到它们?

我想做什么的弗朗西斯科形象

  

我尝试使用以下代码:

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 :(得分:0)

您可以通过方法OnCollisionStay2D(Collision collisionInfo)获得碰撞检测。如果您获得了与发生碰撞的对象的引用,则可以在发生碰撞的对象上调用一个方法,以获取发生碰撞的对象,获取与它们发生碰撞的对象的引用,并销毁gameObject。

希望这会有所帮助!

答案 1 :(得分:0)

好吧,您必须以某种方式转发其他碰撞。

例如,存储冲突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);
        }
    }
}