在VR统一项目中工作,尝试做一些C#脚本。
我的角色模型有两只脚,使用跟踪器在VR中控制。我需要一种方法来找出双脚何时与立方体碰撞。立方体A用于左脚,立方体B用于右脚同时进行。这样我就可以在条件满足时生成另一个对象。
这样做的方法是什么?什么对象应该有脚本?现在,立方体有一个OnTriggerStay函数,用于检查与脚的碰撞并将立方体颜色更改为绿色。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CheckForFoot : MonoBehaviour {
void OnTriggerStay(Collider other)
{
}
}
所以这个脚本放在地板上的立方体上。立方体上有一个与脚相同的collier。当碰撞发生时我现在可以做点什么,但我需要找出如何检查两个相同的立方体是否同时发生碰撞
答案 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);
}