Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Raycast not Returning the expected output.

Discussion in 'Scripting' started by Yatoledieu, Feb 13, 2022.

  1. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6
    Hi everyone, I have a problem with raycasts and I would like to understand why it doesn't work.

    I'm using raycasts to check if there is ground under the player's feet to see if I can place an object under it, it seems like once in 10 times the raycast returns false and I don't know why.

    Like the picture shows the raycast should be returning true cause it should hit the object under him (the red line is a gizmo that shows the raycast direction with the starting point at the top and the endpoint below).

    It seems like if I move the character (like if I just make a simple rotation) the raycast is finally able to return true, it makes no sense.

    Can someone help me with this?

    Let me explain the code, I have made a method that is called in the update method, it checks if the player pressed the jump button and every 0.1s set a boolean called has to place to true.

    In my Fixed Update if the has to place boolean is set to true then I make a raycast to the ground to check if I can place the block under the player feet like this and change the position of the player and the block like this :


    Code (CSharp):
    1. RaycastHit hit;
    2.         //ray to the ground with the height of the block
    3.         Ray ray = new Ray(transform.position, -transform.up * (0.8f + 1));
    4.         //if the raycast hit and the hastoplace true and block available then :
    5.         if (Physics.Raycast(transform.position, transform.TransformVector(Vector3.down), out hit, (0.8f + 1)) && hasToPlace&& manager.CheckAvailable())
    6.         {
    7.             //place the player and the block at the right place
    8.             JumpPlacement(hit.point);
    9.             //reset hastoplace
    10.             hasToPlace = false;
    11.             //if the button is not pressed or the block not available then make a jump
    12.             if (!manager.IsJumpPressed || !manager.CheckAvailable())
    13.             {
    14.                  //method to jump
    15.                 Jump(1.5f);
    16.             }
    17.         }
    The method JumpPlacement as I said earlier place the player and the block at the right place like this :

    Code (CSharp):
    1. public void JumpPlacement(Vector3 pos)
    2.     {
    3.         //return the neaarest block
    4.         GameObject nearest = ReturnNearest(herd);
    5.         //add the block to the list stack to not call it again
    6.         blockStack.Add(nearest.transform);
    7.         //disable player character controller
    8.         manager.Controller.enabled = false;
    9.         //place the player a little upper than the block height
    10.         transform.position = new Vector3(pos.x, pos.y + blockHeight + 1, pos.z);
    11.         //place the block at the hit.point (y axis a little bit upper cause the pivot of the block is at the center of it
    12.         nearest.transform.position = pos + new Vector3(0, 0.4f, 0);
    13.     }
    And then if the player keeps the button pressed, it loops again.



     
    Last edited: Feb 14, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,005
    This usually makes sense when you are raycasting from precisely at the surface instead of lifting the raycast point a bit first, then raycasting.

    Pastes of code are not a thing here. The reason is if they go away, then this post becomes useless and all future users get no learning benefit.

    If you post a code snippet, ALWAYS USE CODE TAGS:

    How to use code tags: https://forum.unity.com/threads/using-code-tags-properly.143875/
     
  3. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6

    Sorry, I didn't know it, I'm going to edit the post so that it fits the rules of the forum, sorry about it.
     
    Bunny83 likes this.
  4. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6
    I don't think I understand what you're saying here.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,005
    If you have an upwards-facing Collider at y == 0 and you raycast downwards from a point at y == 0, it may or may not detect that Collider.

    Are you doing this? If so, then lift the origin of your raycast a little bit.

    Also, you might be hitting other things than you think you are. Use Debug.Log() to find out by:

    - using an overload of Raycast that returns a RaycastHit
    - if you hit something print out the name of the hit.collider within the RaycastHit
     
  6. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6
    At first, I thought this was it but I already tried to make the raycast begin upper than the half of the player height and it didn't solve the problem.



    Code (CSharp):
    1. Debug.Log(Physics.Raycast(transform.position, transform.TransformVector(Vector3.down));
    returns false, that means that the raycast doesn't hit anything right?

    What I don't understand it's that imagine I pressed the button for like 0.4s, then there will be 4 blocks that go under the player's feet, the problem is that once in ten times of restarting the action it only places 3 blocks (cause the raycast return false) while the nine other times it worked well (cause those times the raycasts returned true). And for me, if there was an error in the code it should not work every time, not just once out of ten right?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,005
    Start by putting these two values into local variables first:

    transform.position, transform.TransformVector(Vector3.down));

    Then print them out to the the log. Are they reasonable?

    You must find a way to get the information you need in order to reason about what the problem is.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494
     
    Bunny83 likes this.
  8. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6
    As you said, I've tried to make some debug.log() but it seems like everything alright in the code part, I'm just wondering if moving the transform.position rapidly can make the raycast bug ?
     
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,100
    What transform did you move? your player of the object you want to detect? Moving transforms will not update the physics representation that is used by the physics system. Any object with a collider that moves should have a rigidbody on it and should be moved through the rigidbody.

    If anything else fails, calling Physics.SyncTransforms after a manual change does update the physics scene. Unity does this automatically before a physics simulation step, but in case you just moved a transform / rigidbody, you may need to update the position yourself if frame precise detection is necessary.
     
  10. Yatoledieu

    Yatoledieu

    Joined:
    Oct 23, 2020
    Posts:
    6
    I'm moving the player transform but also the block transform, so you should be right.
    If my player has got a character controller component does this replace the rigid body ?
     
  11. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,100
    Yes, the CharacterController component is an alternative and works essentially outside the physics system. From the physics system's perspective the character controller is just a capsule collider, nothing externally can influence it.