检测来自不同物体的碰撞?

时间:2018-02-09 14:47:18

标签: c# unity3d collision-detection

我无法为这个问题提出合适的标题,但我会解释。

我有一个碰撞盒,里面有一个脚本。此脚本有一个if语句,用于检测来自对象“Cube001”的冲突,并将Debug.Log发送到控制台。

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

 public class cubeDetect : MonoBehaviour {

     void OnCollisionEnter(Collision collision) {

         if (collision.gameObject.name == "Cube001")
         {
             Debug.Log("Cube001 hit!");
         }
     }

 }

使用这种方法,盒子对撞机知道哪个立方体碰到了它,正如我用

指示的那样
collision.gameObject.name == "Cube001"

但是说如果我有10个立方体碰撞碰撞盒,我怎么能更改if语句,而不是编写另外9个if语句来检查它是否接触到碰撞盒,我可以只有1个if语句检测到来自另一个多维数据集的冲突,知道哪个多维数据集命中框,并且凭借这些知识,能够执行Debug.Log以显示其名称点击方框

我已尝试浏览OnCollisionEnter的文档,但找不到任何可以帮助解决这个问题。

3 个答案:

答案 0 :(得分:4)

一种选择是使用相同的名称标记要与之碰撞的所有相似对象。假设我们给他们标签“Cubicle”。然后我们可以做到以下几点:

Gameobject myCube;
void OnCollisionEnter(Collision collision) {

     if (collision.collider.tag == "Cubicle")
     {
         Debug.Log(collision.gameObject.name + " hit!");
         myCube = collision.gameObject; // store colliding gameobject info for use elsewhere
     }
 }

答案 1 :(得分:2)

您需要使用Dictionary。这消除了对所有if语句的需要。

这就是Dictionary应该是这样的:

public static Dictionary<GameObject, System.Action> objToAction = new Dictionary<GameObject, Action>();

然后是一个函数,用于在实例化时将对象添加到字典中,或者如果它们已经存在,则添加到Start函数中

public void registerObject(GameObject obj, System.Action action)
{
    objToAction.Add(obj, action);
}

Dictionary中的键是GameObject(Cube),您也可以使用string(GameObject的名称),但使用GameObject更好。 Dictionary中的值存储了调用OnCollisionEnter时要执行的操作。 因此应该将if语句中的代码置于此处。这是通过Actiondelegate完成的。您可以根据需要添加任意数量的游戏对象(立方体)。

您必须使用上述功能将这些多维数据集对象添加到词典中:

public GameObject prefab;

void Start()
{
    //Create new Cube
    GameObject obj = Instantiate(prefab);
    obj.name = "Cube001";

    //Add it to the Dictionary
    registerObject(obj, delegate { Debug.Log("Hit: " + obj.name); });
}

您的新OnCollisionEnter代码如下所示。无需if语句。如果对象存在于Dictionary中,则为每个关键GameObject执行我们存储在Dictionary值中的代码。

void OnCollisionEnter(Collision collision)
{
    Action action;

    if (objToAction.TryGetValue(collision.gameObject, out action))
    {
        //Execute the approprite code
        action();
    }
}

请注意,objToAction variabel应该是static,或者放在附加到空GameObject的另一个脚本中,以便您可以访问它。应该只有一个实例。

答案 2 :(得分:1)

最适合我的是使用接口和组件并检查它。如果您在碰撞时有某些逻辑,那么这种方法很有效,但是当您不能使用tag并将其设置为类似"collidable"时。

接口解决方案:

public interface ICollidableObject
{
    void CollidedWith(ICollidableObject other);
}

public class CollidableBlock : MonoBehaviour, ICollidableObject
{
    public void CollidedWith(ICollidableObject other)
    {
        Debug.Log((other as MonoBehaviour).gameObject.name);
    }
}

public class CollidableSphere : MonoBehaviour, ICollidableObject
{
    public void CollidedWith(ICollidableObject other)
    {
        Debug.Log("sphere001");
    }
}

就这样使用它:

void OnCollisionEnter(Collision collision) 
{
    ICollidableObject collidedWith = collision.gameObject.GetComponent<ICollidableObject>();
    if ( collidedWith != null )
        collidedWith.CollidedWith(this);
}