Very simple raycast script not working.

Hello,
i am creating a ball rolling game where the ball should never leave the ground.
so i tried to do that with raycasting, but it doesn’t seem to work, the ball is still coming off the ground without a problem, so it seems that my script doesn’t affect my player.

this is my script:

    void StayOnGround ()
    {
        Debug.DrawRay(transform.position, Vector3.down * 200, Color.green);
        RaycastHit hit;
        float distanceToGround = 0;
        if (Physics.Raycast(transform.position, Vector3.down, out hit, 200f))
        {
            distanceToGround = hit.distance;
            transform.position = new Vector2(transform.position.x, transform.position.y - distanceToGround);
        }
    }

and yes i have placed the function in the update, the debug.drawray is working correctly.
What could the problem be?

Thanks in advance,
Timo

A useful trick to troubleshoot raycasts is to use Debug.DrawRay or Debug.DrawLine.
It draws a line in the editor so you can see what the raycast is doing:

http://docs.unity3d.com/ScriptReference/Debug.DrawRay.html
http://docs.unity3d.com/ScriptReference/Debug.DrawLine.html

(I don’t rember which one to use.)

Debug.DrawRay(transform.position, 200.0f * Vector3.down);

if (Physics.Raycast(transform.position, Vector3.down, out hit, 200f))
    {
         distanceToGround = hit.distance;
         transform.position = new Vector2(transform.position.x, transform.position.y - distanceToGround);
   }

i am using the Debug.DrawRay as you can see in the script :slight_smile:

Oh.
Try using
RaycastHit.point

do:
transform.position = new Vector2(transform.position.x, hit.point.y);

It should put the ball right where the raycast hit the ground.

Also, you need to make sure the the raycast is not actually hitting the ball if the ball has a collider. Other wise, the ball would move to its own position;
You could use pass in a layerMask to Physics.Raycast to ignore the layer that the ball is on.
http://docs.unity3d.com/Manual/Layers.html
Do searches on the forum for examples of using creating a layerMask to pass into Raycast

Another way, is to start the raycast out so it starts BELOW the ball, so it doesnt collide with the ball.
example:
Debug.DrawRay(transform.position + 2.0f * Vector3.down, Vector3.down * 200, Color.green);

Hmm… weird. It still doesn’t work,
i’ve screenshotted some settings and my script, did i make a typo somewhere? no right?

I have assigned the Layer “Floor” to the floor object etc.
so it should work.

The approach I use to to put the ball on it’s own layer, and have the raycast ignore that layer.

here is an example:

  int mask = Physics.DefaultRaycastLayers;
       int customMask1 = 0x1 << BALL_LAYER; //Example: BALL_LAYER = 8;

       mask = mask & ~(customMask1);

  bool hit = Physics.Raycast (ray, out hitInfo, distanceToCheck, mask);

Or for now, just put the ball on the IgnoreRaycast layer, and then don’t worry about creating a mask. Because the ball is on the IgnoreRaycast layer, Unity will automatically ignore raycast collisions with the ball.

Personally, i would ignore this method for now, and just try to start the raycast out in a position so it doesn’t hit the ball. (only required if the ball has a collider).
Get that working first. Then you can expirament with the layer method.

alright, my ball does have a collision, and i have setup the raycast like you said, it should ignore the ball since the ball has no layer, and the floor is the only on the layer named floor.
even when i remove the ball collider it doesn’t work i noticed, what could cause this, the debug.raycast shows that it does hit the floor tho.

I would suggest start printing debug statements to the log file to console see what is happening.
Do print statements like:
Debug.Log("The raycast hit: "+hit.collider.name);
Debug.Log("The point of impact is: "+hit.point.y);

To verify what the raycast is hitting and where it is hitting.
Maybe something else is moving the ball?
Is the script attached to the ball?

In the script attached to the ball, put the code in the update function:

void Update()
{

   StayOnGround();
}

You could try forcing the ball to a constant y value to see if that works.

void Update()
{

  transform.position = new Vector3(transform.position.x, 0.0f, transform.position.z);
}

if the ball has a rigidbody, you need to move the position of the rigidbody instead of the transform position.

void Update()
{
  RigidBody rb = GetComponent<RigidBody>(); //EXAMPLE ONLY!!
  rb.position = new Vector3(transform.position.x, 0.0f, transform.position.z);
}

I don’t see why it wouldn’t work unless something else is moving the ball

so far it says that the point of imapact is 0, no matter where the character is at, so i assume it still hits the ball collider
About the collision name, i get an error: NullReferenceException: Object reference not set to an instance of an object.
not sure what’s causing this.
i also forgot to mention that it’s a 2D game, but i am not working with Physics2D, can this cause the problem?

i’ve debugged for a bit, and i created an emtpy game object with just one script, with only the raycasting in it.
and it just doesn’t seem it hit anything.
im going to try using Physics2D now.

I kinda got it working!
It is hitting the player itself now, and when i remove the collider from the player it hits the ground and then it works!
but i can’t seem to get the layer mask working, i have implemented the layermask, but it still hits the player, this is what i’ve got now:

    int layerMask = 1 << 8;

    void OpDeGrondBlijven()
    {

        RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up, layerMask);
        if (hit.collider != null)
        {
            transform.position = new Vector2(transform.position.x, hit.point.y);
            Debug.Log(hit.distance);
        }
        //Debug.Log("you hit " + hit.collider.gameObject.name);
    }

Got it working!

the problem was that i somehow needed to add : Mathf.Infinity to it, not sure why but it works now!

OH wait now!

  1. you need to include the distance AND the layer in order for it to work

you need
RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up, distance, layerMask);

if you just pass the layer to the function Unity thinks that the layer you are sending in the function is the Distance, not the layer

public static RaycastHit2D Raycast(Vector2 origin, Vector2 direction, float distance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, float minDepth = -Mathf.Infinity, float maxDepth = Mathf.Infinity);

It requires: origin, direction, distance, layer