Check if collision between the model and two different objects is happening at the same time

南笙酒味 提交于 2019-12-23 02:53:41

问题


Working in a VR unity project, trying to do some C# scripting.

My character model has two feet that are controlled in VR using trackers. I need a way to find out when both feet are colliding with cubes. cube A for left foot and cube B for the right foot at the same time. So that I can spawn another object when the condition is met.

What would be the way of doing it? What object should have the script? Right now, the cubes have a OnTriggerStay function that checks for collision with feet and changes the cube color to green.

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

public class CheckForFoot : MonoBehaviour {

    void OnTriggerStay(Collider other)
    {



    }
}

So this script is put on the cube that is on the floor. The cube has a collier on it the same as the foot. When the collision happens I can do something now, but I need to find out how to check for two identical cubes are colliding at the same time


回答1:


What would be the way of doing it?

With Collider2D, that would be Physics2D.IsTouching(collider1, collider2) but this is Collider/3D and different no built-in API exist to do this. It's complicated but possible. Here are the steps simplified:

1.Use List of KeyValuePair to store the touching objects.

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

Make it a static variable so that there is only once instance of this list.

2.Detect when there is a trigger with OnTriggerEnter.

The trigger detection script with the OnTriggerEnter function must be attached to each GameObject you want to detect when they are touching each other.

3.Retrieve the two GameObjects that just touched each other.

You can Retrieve the first one by using this.gameObject and the second GameObject by using other.gameObject;. The other variable comes from the Collider other argument in the OnTriggerEnter function.

4.Now, check if both GameObject exist in the collisionList variable from #1. If they don't, add them. If they already exist, ignore it.


5.Just like #2, detect when there is a trigger exit with OnTriggerExit. This means that the Objects are no longer touching.

6.Retrieve the two GameObjects that are no longer touching each other like you did in #3 but in the OnTriggerExit function this time.

7.Now, check if both GameObject exist in the collisionList variable from #1. If they do remove them from that List. If they don't ignore it.

What object should have the script?

Attach the CollisionDetection script to every GameObject you want to detect with another Object. Also make sure that the Collider's IsTrigger is enabled and that a Rigidbody component is attached to each GameObject too.

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:

Just use CollisionDetection.IsTouching(object1, object2) to check if two Objects are touching.

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");
    }
}


来源:https://stackoverflow.com/questions/50409639/check-if-collision-between-the-model-and-two-different-objects-is-happening-at-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!