using UnityEngine; using System.Collections.Generic; using System.Linq; namespace VRSDK { /// /// Collision predictor help us to cast complex collider shapes and check for posibles collisions /// public class CollisionPredictor : MonoBehaviour { [SerializeField] private LayerMask layerMask = new LayerMask(); private List colliderList = null; private Transform collisionPredictorParent = null; private bool collisionCopyCreate = false; private void LateUpdate() { if (!collisionCopyCreate) { CreateCollisionCopy(); SetLayerMask(); RemoveInvalidColliders(); collisionCopyCreate = true; } } private void CreateCollisionCopy() { GameObject clone = Instantiate( gameObject ); RemoveComponents( clone ); if (clone.GetComponent() != null) { Destroy( clone.GetComponent() ); } if (clone.GetComponent() != null) { Destroy( clone.GetComponent() ); } clone.name = gameObject.name + "_CollisionPredictorCopy"; clone.transform.localScale = clone.transform.localScale; collisionPredictorParent = clone.transform; colliderList = clone.GetComponentsInChildren().ToList(); } private void SetLayerMask() { for (int n = 0; n < colliderList.Count; n++) { colliderList[n].gameObject.layer = LayerMask.NameToLayer( "IgnoreCollision" ); } } private void RemoveInvalidColliders() { for (int n = 0; n < colliderList.Count; n++) { if (colliderList[n] is MeshCollider) { Debug.LogWarning("Collider " + colliderList[n].name + " is a MeshCollider, CollisionPredictor does no support MeshColliders"); Destroy(colliderList[n]); colliderList.RemoveAt( n ); n--; } else if (colliderList[n].isTrigger) { Debug.LogWarning("Collider " + colliderList[n].name + " is a trigger collider, removing it from CollisionPredictor"); Destroy( colliderList[n] ); colliderList.RemoveAt( n ); n--; } } } public bool WillCollisionAtPositionAndRotation(Vector3 position , Quaternion rotation ) { //we need to create first our collision copy if (!collisionCopyCreate) return false; //trasnlate the object to the desire postion and rotation collisionPredictorParent.position = position; collisionPredictorParent.rotation = rotation; for (int n = 0; n < colliderList.Count; n++) { if (CheckCollisionAtPosition( colliderList[n] )) return true; } return false; } private bool CheckCollisionAtPosition(Collider collider) { if (collider is SphereCollider) { return PhysicsExtensions.CheckSphere(collider as SphereCollider , layerMask , QueryTriggerInteraction.Ignore); } if (collider is BoxCollider) { return PhysicsExtensions.CheckBox( collider as BoxCollider, layerMask, QueryTriggerInteraction.Ignore ); } if (collider is CapsuleCollider) { return PhysicsExtensions.CheckCapsule(collider as CapsuleCollider , layerMask , QueryTriggerInteraction.Ignore); } return false; } private void RemoveComponents(GameObject go) { Component[] componentArray = go.GetComponentsInChildren(); for (int n = 0; n < componentArray.Length; n++) { if (componentArray[n] != null) { if (componentArray[n] is Canvas) Destroy( componentArray[n].gameObject ); else if (CanDestroyComponent( componentArray[n] )) Destroy( componentArray[n] ); } } } private bool CanDestroyComponent(Component c) { return !( c is Transform ) && !(c is Collider) && !( c is VR_OutlineHighlight) && !( c is VR_Outline ); } } }