Search Unity

Very simple raycast script not working.

Discussion in 'Scripting' started by timoshaddix, Feb 14, 2016.

  1. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    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:
    Code (CSharp):
    1.     void StayOnGround ()
    2.     {
    3.         Debug.DrawRay(transform.position, Vector3.down * 200, Color.green);
    4.         RaycastHit hit;
    5.         float distanceToGround = 0;
    6.         if (Physics.Raycast(transform.position, Vector3.down, out hit, 200f))
    7.         {
    8.             distanceToGround = hit.distance;
    9.             transform.position = new Vector2(transform.position.x, transform.position.y - distanceToGround);
    10.         }
    11.     }
    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
     
  2. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    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.)

    Code (csharp):
    1.  
    2.  
    3. Debug.DrawRay(transform.position, 200.0f * Vector3.down);
    4.  
    5. if (Physics.Raycast(transform.position, Vector3.down, out hit, 200f))
    6.     {
    7.          distanceToGround = hit.distance;
    8.          transform.position = new Vector2(transform.position.x, transform.position.y - distanceToGround);
    9.    }
    10.  
    11.  
     
  3. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    i am using the Debug.DrawRay as you can see in the script :)
     
  4. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    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);
     
    Last edited: Feb 14, 2016
  5. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    Hmm... weird. It still doesn't work,
    i've screenshotted some settings and my script, did i make a typo somewhere? no right?

    http://imgur.com/a/eRJcD

    I have assigned the Layer "Floor" to the floor object etc.
    so it should work.
     
  6. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    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:
    Code (csharp):
    1.  
    2.   int mask = Physics.DefaultRaycastLayers;
    3.        int customMask1 = 0x1 << BALL_LAYER; //Example: BALL_LAYER = 8;
    4.  
    5.        mask = mask & ~(customMask1);
    6.  
    7.   bool hit = Physics.Raycast (ray, out hitInfo, distanceToCheck, mask);
    8.  
    9.  
    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.
     
    Last edited: Feb 14, 2016
  7. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    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.
     
  8. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    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:

    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.  
    5.    StayOnGround();
    6. }
    7.  
    You could try forcing the ball to a constant y value to see if that works.
    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.  
    5.   transform.position = new Vector3(transform.position.x, 0.0f, transform.position.z);
    6. }
    7.  
    if the ball has a rigidbody, you need to move the position of the rigidbody instead of the transform position.
    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.   RigidBody rb = GetComponent<RigidBody>(); //EXAMPLE ONLY!!
    5.   rb.position = new Vector3(transform.position.x, 0.0f, transform.position.z);
    6. }
    7.  
    I don't see why it wouldn't work unless something else is moving the ball
     
    Last edited: Feb 14, 2016
  9. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    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?
     
  10. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    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.
     
  11. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    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:
    Code (CSharp):
    1.     int layerMask = 1 << 8;
    2.  
    3.     void OpDeGrondBlijven()
    4.     {
    5.  
    6.         RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up, layerMask);
    7.         if (hit.collider != null)
    8.         {
    9.             transform.position = new Vector2(transform.position.x, hit.point.y);
    10.             Debug.Log(hit.distance);
    11.         }
    12.         //Debug.Log("you hit " + hit.collider.gameObject.name);
    13.     }
    14.  
     
  12. timoshaddix

    timoshaddix

    Joined:
    Jan 7, 2014
    Posts:
    64
    Got it working!

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

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,835
    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
     
    Last edited: Feb 14, 2016