Is there a way to increment the amount of arguments/objects used by a KeyValuePair?

55 Views Asked by At

I'm using the following code to detect the collision of multiple objects. It is working perfectly well, now what I need is a way to make it work for more than two GameObjects, and I don't have any clue about how to use the KeyValuePair, someone else helped me to write this. I already tried to give KeyValuePair more than two values but it doesn't work.

I'm working on a VR experience where you have different words floating around and if you group them together in the air, they will trigger something else, let's say if you group them you trigger the next lvl or something like that.

I guess that it would be really useful if I could have a dynamic way of changing the KeyValuePair amount of GameObjects, I think I would need for instance to gather more than two words but less than ten, which will complete the all phrase, this will depend on how long the phrase would be.

The groups and detection are based on 3D colliders with rigidbodies marked as IsTrigger.

Any clue about how to extend the KeyValuePair values to use more arguments/colliders/GameObjects?

Thanks!

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

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

public class TestCol : MonoBehaviour
{
    public GameObject Object1;
    public GameObject Object2;

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

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

There are 1 best solutions below

0
derHugo On

No .. a pair consists of exactly two objects ...


I guess you took your code from this answer

You can make your life a lot easier, though!

Why not mapping one object to a HashSet which can hold as many objects you need in a Dictionary<GameObject, HashSet<GameObject>> making also checks if an object is contained in the HashSet way more efficient than going through a list.

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