This has been driving me crazy forever. There are so many situations where you need to do a quick hit test and using onCollision/onTrigger is too hamfisted and bounds doesn’t work because of the rotation issue. Here is my solution. Let me know what you think and please improve it as I am not the most efficient coder:
// Test collision between 2 objects without onCollision/onTrigger and from anywhere.
// Solves the rotation inaccuracies that come from trying to achieve this with "bounds.Intersects()" Rotate either object as you wish!
// is probably inefficient. Feel free to improve!
// WARNING: You need to create a level 22 in your Unity editor and have nothing on it for this to work properly
// to test against layer: hitTest(goRef1, null, 8, "box")==1
// to test against other go: hitTest(goRef1, goRef2, 0, "box")==1 - layer is ignored here, put in any number
// RAY can be:
// box: a bounding box measurement. Good for square objects. Recommended in most cases.
// point: 3 lines draw from max/min x,y,z to form a cross in the center. Good for rounder objects.
// hover: Probably nothing you'll need.
function hitTest(go:GameObject, target:GameObject, layer:int, ray:String){
var hit : RaycastHit;
var mode = "layer";
if(target!=null){
layer = target.layer;
mode = "object";
}
//set up directions
var d1 = go.transform.TransformDirection (Vector3.right);
var d2 = go.transform.TransformDirection (Vector3.left);
var d3 = go.transform.TransformDirection (Vector3.up);
var d4 = go.transform.TransformDirection (Vector3.down);
var d5 = go.transform.TransformDirection (Vector3.forward);
var d6 = go.transform.TransformDirection (-Vector3.forward);
//normalize angles to get proper measurements
var saveRot:Vector3 = go.transform.eulerAngles;
go.transform.eulerAngles = Vector3.zero;
var bounds = go.renderer.bounds;
var r1 = new Vector3(bounds.extents.x * d1.x, bounds.extents.x * d1.y, bounds.extents.x * d1.z);
var r2 = new Vector3(bounds.extents.x * d2.x, bounds.extents.x * d2.y, bounds.extents.x * d2.z);
var r3 = new Vector3(bounds.extents.y * d3.x, bounds.extents.y * d3.y, bounds.extents.y * d3.z);
var r4 = new Vector3(bounds.extents.y * d4.x, bounds.extents.y * d4.y, bounds.extents.y * d4.z);
var r5 = new Vector3(bounds.extents.z * d5.x, bounds.extents.z * d5.y, bounds.extents.z * d5.z);
var r6 = new Vector3(bounds.extents.z * d6.x, bounds.extents.z * d6.y, bounds.extents.z * d6.z);
go.transform.eulerAngles = saveRot;
if(ray=="point"){
v1= new Vector3(go.transform.position.x + r1.x,go.transform.position.y + r1.y,go.transform.position.z + r1.z);
v2= new Vector3(go.transform.position.x + r2.x,go.transform.position.y + r2.y,go.transform.position.z + r2.z);
v3= new Vector3(go.transform.position.x + r3.x,go.transform.position.y + r3.y,go.transform.position.z + r3.z);
v4= new Vector3(go.transform.position.x + r4.x,go.transform.position.y + r4.y,go.transform.position.z + r4.z);
v5= new Vector3(go.transform.position.x + r5.x,go.transform.position.y + r5.y,go.transform.position.z + r5.z);
v6= new Vector3(go.transform.position.x + r6.x,go.transform.position.y + r6.y,go.transform.position.z + r6.z);
if(mode=="layer"){
layerMask = 1 << layer;
}else if(mode=="object"){
var saveLayer = go.layer;
target.layer = 22;
layerMask = 1 << 22;
}
if (Physics.Raycast (v1, d2, hit, bounds.extents.x*2, layerMask)) {
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v2, d1, hit, bounds.extents.x*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v3, d4, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v4, d3, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v5, d6, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v6, d5, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}
//none of the raycasts detected anything, but our g.o. could be completely inside the target layer or object which will throw the detection off
//now test to to see if the object is inside
if(checkToSeeIfItsInside(go, layer)==true){
return 1;
}
return 3;
}else if(ray=="box"){
//
v1= new Vector3(go.transform.position.x + r1.x + r3.x + r5.x,go.transform.position.y + r1.y + r3.y + r5.y,go.transform.position.z + r1.z + r3.z + r5.z);
v2= new Vector3(go.transform.position.x + r2.x + r3.x + r5.x,go.transform.position.y + r2.y + r3.y + r5.y,go.transform.position.z + r1.z + r3.z + r5.z);
v3= new Vector3(go.transform.position.x + r2.x + r3.x + r6.x,go.transform.position.y + r2.y + r3.y + r6.y,go.transform.position.z + r2.z + r3.z + r6.z);
v4= new Vector3(go.transform.position.x + r1.x + r3.x + r6.x,go.transform.position.y + r1.y + r3.y + r6.y,go.transform.position.z + r1.z + r3.z + r6.z);
v5= new Vector3(go.transform.position.x + r1.x + r4.x + r5.x,go.transform.position.y + r1.y + r4.y + r5.y,go.transform.position.z + r1.z + r4.z + r5.z);
v6= new Vector3(go.transform.position.x + r2.x + r4.x + r5.x,go.transform.position.y + r2.y + r4.y + r5.y,go.transform.position.z + r2.z + r4.z + r5.z);
v7= new Vector3(go.transform.position.x + r2.x + r4.x + r6.x,go.transform.position.y + r2.y + r4.y + r6.y,go.transform.position.z + r2.z + r4.z + r6.z);
v8= new Vector3(go.transform.position.x + r1.x + r4.x + r6.x,go.transform.position.y + r1.y + r4.y + r6.y,go.transform.position.z + r1.z + r4.z + r6.z);
if(mode=="layer"){
layerMask = 1 << layer;
}else if(mode=="object"){
saveLayer = go.layer;
target.layer = 22;
layerMask = 1 << 22;
}
//down sides
if(Physics.Raycast (v1, d4, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v2, d4, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v3, d4, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v4, d4, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
//up sides
}else if(Physics.Raycast (v5, d3, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v6, d3, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v7, d3, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v8, d3, hit, bounds.extents.y*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
//top
}else if (Physics.Raycast (v1, d2, hit, bounds.extents.x*2, layerMask)) {
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v2, d6, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v3, d1, hit, bounds.extents.x*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v4, d5, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
//bot
}else if(Physics.Raycast (v5, d2, hit, bounds.extents.x*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v6, d6, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v7, d1, hit, bounds.extents.x*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}else if(Physics.Raycast (v8, d5, hit, bounds.extents.z*2, layerMask)){
if(mode=="object"){
target.layer = saveLayer;
}
return 1;
}
if(checkToSeeIfItsInside(go, layer)==true){
return 1;
}
return 3;
}else if(ray=="hover"){
var starts : Array = new Array();;
v1= new Vector3(go.transform.position.x + r1.x,go.transform.position.y + r1.y,go.transform.position.z + r1.z);
v2= new Vector3(go.transform.position.x + r2.x,go.transform.position.y + r2.y,go.transform.position.z + r2.z);
v3= new Vector3(go.transform.position.x + r3.x,go.transform.position.y + r3.y,go.transform.position.z + r3.z);
v4= new Vector3(go.transform.position.x + r4.x,go.transform.position.y + r4.y,go.transform.position.z + r4.z);
v5= new Vector3(go.transform.position.x + r5.x,go.transform.position.y + r5.y,go.transform.position.z + r5.z);
v6= new Vector3(go.transform.position.x + r6.x,go.transform.position.y + r6.y,go.transform.position.z + r6.z);
v7= new Vector3(go.transform.position.x + r1.x + r3.x + r5.x,go.transform.position.y + r1.y + r3.y + r5.y,go.transform.position.z + r1.z + r3.z + r5.z);
v8= new Vector3(go.transform.position.x + r2.x + r3.x + r5.x,go.transform.position.y + r2.y + r3.y + r5.y,go.transform.position.z + r1.z + r3.z + r5.z);
v9= new Vector3(go.transform.position.x + r2.x + r3.x + r6.x,go.transform.position.y + r2.y + r3.y + r6.y,go.transform.position.z + r2.z + r3.z + r6.z);
v10= new Vector3(go.transform.position.x + r1.x + r3.x + r6.x,go.transform.position.y + r1.y + r3.y + r6.y,go.transform.position.z + r1.z + r3.z + r6.z);
v11= new Vector3(go.transform.position.x + r1.x + r4.x + r5.x,go.transform.position.y + r1.y + r4.y + r5.y,go.transform.position.z + r1.z + r4.z + r5.z);
v12= new Vector3(go.transform.position.x + r2.x + r4.x + r5.x,go.transform.position.y + r2.y + r4.y + r5.y,go.transform.position.z + r2.z + r4.z + r5.z);
v13= new Vector3(go.transform.position.x + r2.x + r4.x + r6.x,go.transform.position.y + r2.y + r4.y + r6.y,go.transform.position.z + r2.z + r4.z + r6.z);
v14= new Vector3(go.transform.position.x + r1.x + r4.x + r6.x,go.transform.position.y + r1.y + r4.y + r6.y,go.transform.position.z + r1.z + r4.z + r6.z);
starts.Push(v1);starts.Push(v2);starts.Push(v3);starts.Push(v4);starts.Push(v5);starts.Push(v6);starts.Push(v7);starts.Push(v8);starts.Push(v9);starts.Push(v10);starts.Push(v11);starts.Push(v12);starts.Push(v13);starts.Push(v14);
if(mode=="layer"){
layerMask = 1 << layer;
}else if(mode=="object"){
saveLayer = go.layer;
target.layer = 22;
layerMask = 1 << 22;
}
//down sides
var hits = 0;
for(var sp=0; sp<starts.length; sp++){
starts[sp].y = 600;
if(Physics.Raycast (starts[sp], Vector3.down, hit, 605, layerMask)){
hits++;
}
}
if(mode=="object"){
target.layer = saveLayer;
}
var perc:float = (hits*100)/14;
return perc;
}
}
function checkToSeeIfItsInside(go:GameObject, layer:int){
var hit : RaycastHit;
var all : GameObject[] = FindObjectsOfType(GameObject) as GameObject[];
for (var ob : GameObject in all) {
if(ob.layer==layer){
//cycle through all go's in layer
var saveLayer = ob.layer;
ob.layer=22;
//now that everything is out of the way, raycast in all directions to see if the ray only hits the ob
var ac = 1000;
layerMask = 1<<22;
var s1 = new Vector3(go.transform.position.x+ac, go.transform.position.y, go.transform.position.z);
var s2 = new Vector3(go.transform.position.x-ac, go.transform.position.y, go.transform.position.z);
var s3 = new Vector3(go.transform.position.x, go.transform.position.y+ac, go.transform.position.z);
var s4 = new Vector3(go.transform.position.x, go.transform.position.y-ac, go.transform.position.z);
var s5 = new Vector3(go.transform.position.x, go.transform.position.y, go.transform.position.z+ac);
var s6 = new Vector3(go.transform.position.x, go.transform.position.y, go.transform.position.z-ac);
if (Physics.Raycast (s1, Vector3.left, hit, ac*2, layerMask) && Physics.Raycast (s2, Vector3.right, hit, ac*2, layerMask) && Physics.Raycast (s3, Vector3.down, hit, ac*2, layerMask) && Physics.Raycast (s4, Vector3.up, hit, ac*2, layerMask) && Physics.Raycast (s5, -Vector3.forward, hit, ac*2, layerMask) && Physics.Raycast (s6, Vector3.forward, hit, ac*2, layerMask)) {
hasHit=true;
ob.layer=saveLayer;
return true;
}
ob.layer=saveLayer;
}
}
}