- Home /
The question is answered, right answer was accepted
How can I detect which SIDE of a box I collided with?
INFO.... I am using an empty with 4 cubes (That have Ridgedbodys & Box colliders and using the "function OntriggerEnter") to make up my gameobject "BLOCk". My BLOCK will be my player and drop to the floor(A Plane) slowly, if it hits the floor or the top of another BLOCK it will kill the movement script and create another BLOCK to control at the top.
Question.... I want to DoSomething if I hit the "TOP" of a different BLOCK but DoSomething else if I hit the "SIDE" of that BLOCK.
I would like to keep it simple and not use a char controller, but from what I am reading that might not be an option. I was thinking of using a raycast maybe.
I am using this right now for my floor detection.
// When collides with something
function OnTriggerEnter(other : Collider)
{
// gets the BlockS Object
var block = gameObject.Find("BlockS");
// Gets the movement script on the blocks object
var movementscript = block.GetComponent(BlockMovement);
// if the block collides with the floor
if( other.gameObject.tag == "WallFloor")
{
movementscript.enabled = false;
}
Ok so as I am looking through the answers I figured I would give you more detail into what I am doing. The Block will be made of of cubes all having there own collision box. The BLOC$$anonymous$$ can be rotated by 90 degrees along all three axis by the player as it falls. I have a plane as the walls and floor and use onTriggerEnter to tell when I need to stop the cube from moving in that direction. Right now my BLOC$$anonymous$$S will stop at the floor and the walls but go right through each other. The Problem I need help with is to find the easiest way to get my BLOC$$anonymous$$S to stack and stop moving in the Y axis if on top of another BLOC$$anonymous$$ or stop moving in the X or Z axis if colliding with the side of another BLOC$$anonymous$$. I am also using "transform.position.x = transform.position.x -1;" to move my object because I need it to move exactly 1 space to keep everything where it should be.
Answer by sparkzbarca · Oct 30, 2012 at 04:44 AM
umm collision detection doesnt really work if your going to transform move stuff.
If you need collision detection you need a rigidbody, you normally move rigidbodies with physics. If your moving them with transform move you should mark as is kinematic. That means it will not be moved by physics but by transform.
A kinematic rigidbody which you want to move should be done during FixedUpdate to apply collisions properly.
if you would like to know which side you hit you may raycast to the object
this code snippet shows a raycast you could perform on collision.
//this ray will generate a vector which points from the center of
//the falling object TO object hit. You subtract where you want to go from where you are
Ray MyRay = ObjectHit.position - ObjectFalling.position;
//this will declare a variable which will store information about the object hit
raycasthit MyRayHit;
//this is the actual raycast
raycast(MyRay, out MyRayHit);
//this will get the normal of the point hit, if you dont understand what a normal is
//wikipedia is your friend, its a simple idea, its a line which is tangent to a plane
vector3 MyNormal = MyRayHit.normal;
//this will convert that normal from being relative to global axis to relative to an
//objects local axis
MyNormal = MyRayHit.transform.transformdirection(MyNormal);
//this next line will compare the normal hit to the normals of each plane to find the
//side hit
if(MyNormal == MyRayHit.transform.up)
{
you hit the top plane, act accordingly
}
//important note the use of the '-' sign this inverts the direction, -up == down. Down doesn't exist as a stored direction, you invert up to get it.
if(MyNormal == -MyRayHit.transform.up)
{
you hit the bottom plane act accordingly
}
if(MyNormal == MyRayHit.transform.right)
{
hit right
}
//note the '-' sign converting right to left
if(MyNormal == -MyRayHit.transform.right)
{
hit left
}
compare mynormal to transform.forward and -transform.forward for the front and back plane.
now you simply stop movement in the appropriate way. Please mark as answered. :)
So I'm having the same problem the OP is having, and well stumbled across this.
Problem being you can't convert a Vector3 to a Ray. So how would could that work?
why would you want to convert a vector 3 to a ray. Are you using a box? for a box the code should work you compare the normal of the surface hit to the known normals of the sides of the boxes to know where you hit.
When I try to run this code, it gives me plenty of errors, not including the insides of the if
statements. Could you please update this with working code?
@sparkzbarca thanks for the nice concept. Saved lots of my hours. cheers :)
Answer by Fattie · Sep 28, 2015 at 01:51 PM
"How can I detect which SIDE of a box I collided with?"
The very simple, absolutely reliable, way to do this is just add six colliders, one on each side
It's then extremely easy.
After all, say you have a car model. This is precisely what you do to detect collisons on, say, the doors versus the roof or the various bumpers.
Enjoy - it's very easy.
Answer by OregonOx · Feb 10, 2016 at 08:04 PM
Here is code above working in C#
Cheers!
using UnityEngine;
using System.Collections;
public class GetSideHit : MonoBehaviour {
/************************************************************
** Make sure to add rigidbodies to your objects.
** Place this script on your object not object being hit
** this will only work on a Cube being hit
** it does not consider the direction of the Cube being hit
** remember to name your C# script "GetSideHit"
************************************************************/
void OnCollisionEnter( Collision collision ){
Debug.Log( ReturnDirection( collision.gameObject, this.gameObject ) );
}
private enum HitDirection { None, Top, Bottom, Forward, Back, Left, Right }
private HitDirection ReturnDirection( GameObject Object, GameObject ObjectHit ){
HitDirection hitDirection = HitDirection.None;
RaycastHit MyRayHit;
Vector3 direction = ( Object.transform.position - ObjectHit.transform.position ).normalized;
Ray MyRay = new Ray( ObjectHit.transform.position, direction );
if ( Physics.Raycast( MyRay, out MyRayHit ) ){
if ( MyRayHit.collider != null ){
Vector3 MyNormal = MyRayHit.normal;
MyNormal = MyRayHit.transform.TransformDirection( MyNormal );
if( MyNormal == MyRayHit.transform.up ){ hitDirection = HitDirection.Top; }
if( MyNormal == -MyRayHit.transform.up ){ hitDirection = HitDirection.Bottom; }
if( MyNormal == MyRayHit.transform.forward ){ hitDirection = HitDirection.Forward; }
if( MyNormal == -MyRayHit.transform.forward ){ hitDirection = HitDirection.Back; }
if( MyNormal == MyRayHit.transform.right ){ hitDirection = HitDirection.Right; }
if( MyNormal == -MyRayHit.transform.right ){ hitDirection = HitDirection.Left; }
}
}
return hitDirection;
}
}
Hi, I used this code with boxes and it worked perfectly. As you said above, it only works on a Cube. However, I would like to use it on my imported object from max. It didn't show me anything. Simply Raycast ignores my objects. Is there any problem with meshes when using direction vectors ? Could you give me more information what is the problem of the other objects?
Is this the code which assumes you installed 6 box colliders on each face of a RigidBody ameobject cube?