- Home /
raycast collision not behaving as expected
I am using raycast to detect whether a rigidbody is on the ground. When I play the game initially, the body is in the air and the raycast detects that it is not hitting anything, however once the body has hit the ground, if it leaves the surface again the raycast still returns a hit. I have lowered the length of the raycast as much as I can and can see in the play preview that the ray is not hitting anything. I have also narrowed it down to one particular collider but no dice.. Here is the code -
function FixedUpdate() {
Debug.DrawRay (transform.position, -Vector3.up * 0.07);
var hit : RaycastHit; var rayDown = transform.TransformDirection(-Vector3.up);
if (Physics.Raycast (this.transform.position, rayDown, hit, 0.07)) {
if(hit.collider.tag == "floor"){
hitnormal = hit.normal;
hitting = true;
print("hitting floor"); //this prints once the body hits the ground initially
}else { //close ifTwo / open else
print("no hit"); //this never prints
hitting = false;
}
}
myDirection = transform.TransformDirection(Vector3.forward); var temp : Vector3 = Vector3.Cross(hitnormal, myDirection); var myDirection : Vector3 = Vector3.Cross(temp, hitnormal);
//forward vector relative to camera var forward=transform.TransformDirection(Vector3.forward); //reset y to walk horizontally, so that camera looking up doesnt matter forward.y=0;
//normalize to apply speed later
forward=myDirection.normalized;
//right vector relative to the camera, to strafe var right=Vector3(forward.z, 0, -forward.x);
//make the player always look forward relatively to the camera transform.rotation=Quaternion.LookRotation(forward);
//controls when grounded / not flying if (hitting) {
var myTurn = Input.GetAxis("Horizontal")*Time.deltaTime*turnSpeed;
var myStrafe = Input.GetAxis("Horizontal")*Time.deltaTime*strafeSpeed;
transform.Rotate(Vector3.up * myTurn);
transform.Translate(Vector3.right * myStrafe);
var myFwd = transform.TransformDirection(Vector3.forward);
rigidbody.AddRelativeForce(0,0,50);
//this next bit works initially before the player hits the ground
//but not after it has hit the ground once
} else if (!hitting) {
var noTurn : float = 0.0; var noStrafe : float = 0.0; transform.Rotate(Vector3.up noTurn); transform.Translate(Vector3.right noStrafe);
rigidbody.AddRelativeForce(0,0,0);
print("not");
}
I am really new to this so would really appreciate some help - thank you :)
Answer by Nicolaj Schweitz · Feb 09, 2010 at 09:22 PM
You can check for ground collisions a dozen of ways. Checking the collision's normal could be an alternative to using ray casting:
function OnCollisionStay(c:Collision) { var cNormal:Vector3 = c.contacts[0].normal;
if (cNormal == Vector3.up)
Debug.Log("I'm on a vertical surface...");
}
I'm not sure how efficient it is, but it detects the ground at least.
thanks for your answer, have managed to get round it now :)
Answer by Jason_DB · Feb 21, 2010 at 03:00 PM
I think the issue is that you are basing it on the tag "floor", which means that when you are in the air the raycast will not hit anything and will not return a tag (would stop it from overwriting the existing hit.tag of "floor" and from registering that you aren't on the ground anymore). What you could do is just determine whether or not the raycast hit anything regardless of its tag.
This might not be the exact way to code it but here's what I mean:
if(hit != null){
hitnormal = hit.normal;
hitting = true;
print("hitting floor"); //this prints once the body hits the ground initially
}else { //close ifTwo / open else
print("no hit"); //this never prints
hitting = false;
}