检查模型与两个不同对象之间是否同时发生碰撞

时间:2018-05-18 10:47:12

标签: c# unity3d events triggers

在VR统一项目中工作,尝试做一些C#脚本。

我的角色模型有两只脚,使用跟踪器在VR中控制。我需要一种方法来找出双脚何时与立方体碰撞。立方体A用于左脚,立方体B用于右脚同时进行。这样我就可以在条件满足时生成另一个对象。

这样做的方法是什么?什么对象应该有脚本?现在,立方体有一个OnTriggerStay函数,用于检查与脚的碰撞并将立方体颜色更改为绿色。

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

public class CheckForFoot : MonoBehaviour {

    void OnTriggerStay(Collider other)
    {



    }
}

所以这个脚本放在地板上的立方体上。立方体上有一个与脚相同的collier。当碰撞发生时我现在可以做点什么,但我需要找出如何检查两个相同的立方体是否同时发生碰撞

2 个答案:

答案 0 :(得分:2)

  

这样做的方法是什么?

使用Collider2D,这将是Physics2D.IsTouching(collider1, collider2),但这是Collider / 3D,并且不存在相同的内置API。这很复杂但可能。以下是简化的步骤:

1 。使用List KeyValuePair来存储触摸对象。

static private List<KeyValuePair<GameObject, GameObject>> collisionList;

将其设为static变量,以便该列表只有一次实例。

2 。当有OnTriggerEnter的触发器时检测。

具有OnTriggerEnter功能的触发器检测脚本必须附加到每个要在彼此接触时检测的GameObject。

3 。检索刚碰到的两个GameObjects。

您可以使用this.gameObject检索第一个,使用other.gameObject;检索第二个GameObject。 other变量来自Collider other函数中的OnTriggerEnter参数。

4 。现在,检查两个GameObject是否存在于#1 collisionList变量中。如果他们不这样做,请添加它们。如果它们已经存在,请忽略它。

5 。只需#2 ,检测何时触发退出OnTriggerExit。这意味着物体不再接触。

6 。检索两个不再相互影响的游戏对象,就像你在#3 中一样,但这次在OnTriggerExit函数中。

7 。现在,检查两个GameObject是否存在于#1 collisionList变量中。如果他们确实从该列表中删除它们。如果他们不理睬它。

  

脚本应该有什么对象?

CollisionDetection脚本附加到要用另一个Object检测的每个GameObject。还要确保Collider的IsTrigger为enabled,并且Rigidbody组件也附加到每个GameObject。

using System.Collections.Generic;
using UnityEngine;

public class CollisionDetection: MonoBehaviour

{
    static private List<KeyValuePair<GameObject, GameObject>> collisionList =
        new List<KeyValuePair<GameObject, GameObject>>();

    void OnTriggerEnter(Collider other)
    {
        //Debug.Log("Trigger Entered");

        //Get the two Objects involved in the collision
        GameObject col1 = this.gameObject;
        GameObject col2 = other.gameObject;

        //Add to the collison List
        RegisterTouchedItems(collisionList, col1, col2);
    }

    void OnTriggerExit(Collider other)
    {
        //Debug.Log("Trigger Exit");

        //Get the two Objects involved in the collision
        GameObject col1 = this.gameObject;
        GameObject col2 = other.gameObject;

        //Remove from the collison List
        UnRegisterTouchedItems(collisionList, col1, col2);
    }

    public static bool IsTouching(GameObject obj1, GameObject obj2)
    {
        int matchIndex = 0;
        return _itemExist(collisionList, obj1, obj2, ref matchIndex);
    }

    private void UnRegisterTouchedItems(List<KeyValuePair<GameObject, GameObject>> existingObj, GameObject col1, GameObject col2)
    {
        int matchIndex = 0;

        //Remove if it exist
        if (_itemExist(existingObj, col1, col2, ref matchIndex))

        {
            existingObj.RemoveAt(matchIndex);
        }
    }

    private void RegisterTouchedItems(List<KeyValuePair<GameObject, GameObject>> existingObj, GameObject col1, GameObject col2)
    {
        int matchIndex = 0;

        //Add if it doesn't exist
        if (!_itemExist(existingObj, col1, col2, ref matchIndex))

        {
            KeyValuePair<GameObject, GameObject> item = new KeyValuePair<GameObject, GameObject>(col1, col2);
            existingObj.Add(item);
        }
    }

    private static bool _itemExist(List<KeyValuePair<GameObject, GameObject>> existingObj, GameObject col1,
    GameObject col2, ref int matchIndex)
    {
        bool existInList = false;
        for (int i = 0; i < existingObj.Count; i++)
        {
            //Check if key and value exist and vice versa
            if ((existingObj[i].Key == col1 && existingObj[i].Value == col2) ||
                    (existingObj[i].Key == col2 && existingObj[i].Value == col1))
            {
                existInList = true;
                matchIndex = i;
                break;
            }
        }
        return existInList;
    }

}

<强> USAGE:

只需使用CollisionDetection.IsTouching(object1, object2)检查两个物体是否正在接触。

public GameObject foot1;
public GameObject foot2;

void Update()
{
    //Check if feet GameObjects are touching 
    bool touching = CollisionDetection.IsTouching(foot1, foot2);

    if (touching)
    {
        Debug.Log("<color=green>leg1 and leg2 touching</color>");
    }
    else
    {
        Debug.Log("leg1 and leg2 NOT touching");
    }
}

答案 1 :(得分:0)

使用不同的数据结构可以大大改善公认的答案!

为什么不将一个对象映射到可以容纳Dictionary<GameObject, HashSet<GameObject>>中所需数量的对象的HashSet,同时还要检查HashSet中包含的对象是否比通过列表更有效。

private static Dictionary<GameObject, HashSet<GameObject>> collisions =
    new Dictionary<GameObject, HashSet<GameObject>>();

private void Awake ()
{
    // Create a new entry in the Dictionary for this object
    collisions.Add(gameObject, new HashSet<GameObject>());
}

void OnTriggerEnter(Collider other)
{
    // Your Register method basically becomes that simple
    if(!collisions [gameObject].Contains(other.gameObject))
    {
        collisions[gameObject].Add(other.gameObject);
    }
}

void OnTriggerExit(Collider other)
{
    // And accordingly the unregister
    if(collisions [gameObject].Contains(other.gameObject))
    {
        collisionss[gameObject].Remove(other.gameObject);
    }
}

// Also the getter for your touches becomes way simpler
public static bool IsTouching(GameObject obj1, GameObject obj2)
{
    if(!collisions.ContainsKey(obj1)
    {
        return false;
    }

    return collisions[obj1].Contains(obj2);
}

private void OnDestroy ()
{
    // remove the entry for this object
    collisions.RemoveKey(gameObject);
}