【问题标题】:How to get collisions of collisions in unity2d? And what is wrong with this code?如何在unity2d中获得碰撞的碰撞?这段代码有什么问题?
【发布时间】:2019-01-31 13:50:48
【问题描述】:

我有圆形游戏对象预制件。我随机实例化它们大约 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
    }
}

【问题讨论】:

  • 为什么现在只检查标签删除OnTriggerExit中的所有内容?
  • 我看到并修复了,但我在这个项目上工作了大约 5-7 个小时,我之前写得很好。它没有给出编码错误。但我无法得到所有对撞机。这段代码只是为了给你看。

标签: unity3d collision-detection collision


【解决方案1】:

您可以通过OnCollisionStay2D(Collision collisionInfo)方法获得碰撞检测。如果你获得了碰撞对象的引用,你可以调用碰撞对象上的方法来获取碰撞对象,获取碰撞对象的引用,然后销毁游戏对象。

希望这会有所帮助!

【讨论】:

  • 在这里我有一个问题。 A 与 B 碰撞。但 A 不与 C 和 D 碰撞。​​如果我破坏 A 并且其他人与它碰撞,则仅删除 A 和 B。我可以得到 A 的对撞机。我怎样才能得到与 A 碰撞的 B 的对撞机?
  • 将一个脚本(有一个方法来返回它正在碰撞的对象)添加到你正在碰撞的东西上,然后当你与那个对象发生碰撞时,使用将返回的引用调用该方法与它碰撞的第二个对象的对象,然后将它们全部删除。
  • 类似references = collisionInfo.GetComponent&lt;MyClass&gt;().myMethod(),然后是Destroy(collisionInfo.gameObject)Destroy(references.gameObject)。这是伪代码。
【解决方案2】:

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

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

【讨论】:

  • 我使用它,但它给出了一堆错误。 (注意:我编辑了所有内容以适应我的游戏没有问题)这段代码不是 c# 吗?我有 5 个不同的对象预制件。我随机生成它们。我希望预制件控制它附近具有相同标签的其他预制件并将它们添加到列表中(我做到了)然后找到靠近它的预制件附近的预制件并将它们也添加到相同的列表中。(这是我在哪里卡住)
  • 您遇到什么错误?而且“近”不等于“碰撞”。当然,您可以将它们全部添加到一个列表中,而不是销毁对象。
  • 我编辑了所有问题并添加了参考图像和代码
  • 我仍然看不到我的代码有什么错误?而不是调用Destroy,您可以更改方法并将它们全部收集到一个列表中
  • 你为 3d 写的。我无法将其修复为 2d。 unity2d 中没有“碰撞”方法。我把它设为列表。因此,我无法玩游戏“List(){this})”统一为“this”提供错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 2011-05-06
  • 1970-01-01
相关资源
最近更新 更多