- Home /
Detecting when an object enters a collider from the top?
My character with character controller rolls around, and sometimes hits my object which has a box collider. I want to do so that if i hit the object from above, the object plays one animation, and if the object is hit from any other side, it should play another. I know how to do the animation part, so all I need help with is how to detect where the collision happens.
Any ideas how to go about this one?
Answer by aldonaletto · Oct 28, 2012 at 05:32 PM
You could use OnControllerColliderHit in the character script, and check the hit normal: if it's almost vertical, you're colliding in the top-down direction. But there's an issue: this event happens all the time due to collisions with the ground, thus you should filter out the undesired cases checking if the collided object has the right tag. Another problem: the animation code probably is attached to the hit object, not to the character, thus you should pass a hint from the character script to the animation code.
An example: the animation script (let's call it AnimScript.js) could contain a function like this:
function PlayAnimation(normal: Vector3){
if (normal.y > 0.9){ // if hit normal angle from horizontal > 64 degrees (sin(64)=0.9)
animation.CrossFade("TopDownHit"); // play top-down animation
} else {
animation.CrossFade("OtherHit"); // play other animation
}
}
And in the character script you could have a code like this:
function OnControllerColliderHit(hit: ControllerColliderHit){
if (hit.transform.tag == "Enemy"){ // supposing the other object is tagged Enemy
// try to get its script AnimScript.js
var anim: AnimScript = hit.transform.GetComponent(AnimScript);
// if script got, call PlayAnimation passing the hit normal:
if (anim) anim.PlayAnimation(hit.normal);
}
}
Okay so I understand how to check for tags and send messages between objects etc.
I now understand that you can check for the hit normal, but I don't quite understand THAT. How does that work in more detail, if you would be so kind to explain? :D
EDIT: Thanks for taking your time to help of course! :)
Alright so in the script reference I found the bit of code you use to recieve the normal which you collide at. One problem though; I simply use Send$$anonymous$$essage, to tell my object i hit to play an animation, but I cannot use Send$$anonymous$$essage if the object i collide with is not set to Is Trigger! The other way around, I cannot get the hit normal if my object IS trigger... What do I do here?
EDIT: I just wrote the code wrong, I can use sendmessage just fine. Problem solved!
Send$$anonymous$$essage is a good alternative - a little slower than a direct call, but more versatile: since the function is called by name, the character script doesn't have to know the target script at compile time.
About the normal: being a normalized vector, its Y component is numerically equal to the sin of the elevation angle (angle relative to the horizontal plane XZ). If normal.y is higher than 0.9 (sin of 64 degrees), we know that the hit surface is almost horizontal (inside +/- 26 degrees range) and facing up.