Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Unable to get Raycast to hit an object; believes there's a clear path to object, but there isn't.

Discussion in 'Scripting' started by ferrinmass, Jun 23, 2023.

  1. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8

    In the image you see how the Raycast goes straight through the object. RaycastHit however returns no hits. In fact, on rare occasions it returns a hit, but it's rare. I'm guessing it has to do with Update/FixedUpdate/LateUpdate. Since it's camera work, I put my code in LateUpdate.

    I tried the others just for kicks, and as expected, it has consistent 0 hits, and the Raycast misses the object every single time.

    I'm not sure how to fix this issue, but what I do know is that Raycast doesn't return a hit when it should. :\ Any ideas, folks?

    Code goes like this, where otherObject is... another specific object that is not the blue planet in the image:


    Code (CSharp):
    1. bool IsOtherObjectHidingBehindThatBlueSphereInTheImage(...)
    2.     {
    3.         Vector3 direction = otherObject - mainCamera.transform.position;
    4.         Ray ray = new(mainCamera.transform.position, direction.normalized);
    5.  
    6.         Debug.DrawRay(mainCamera.transform.position, direction, Color.red);
    7.  
    8.         if (Physics.Raycast(ray, out RaycastHit hit))
    9.         {
    10.             if (hit.transform != otherObject)
    11.             {
    12.                 return true;
    13.             }
    14.         }
    15.  
    16.         return false;
    17.  
    18.     }
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    Check the Collider. Enable collider drawing in the scene view and check if it matches that object's size. Currently I don't see a collider drawing around that sphere so either collider drawing is disabled or the collider is far too small or too big.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    You can run physics queries whenever you like, it's doesn't matter when you call them. In the end, the collider is either there or it isn't.

    What I don't understand is the "otherObject". What is that? If it's a Transform then shouldn't you get the direction with "otherObject.position - mainCamera.transform.position" instead?
     
  4. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    There is a collider. Like I said, it hits sometimes. You don't see a collider because that object is not selected. The collider properly envelops the object. :(
     
  5. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    The "otherObject" doesn't matter. It's just a point in space that establishes the direction from the camera. This is also besides the point. The raycast isn't seeing the blue sphere, most of the time, when in LateUpdate. It never sees the blue sphere, ever, when in Update or FixedUpdate.
     
  6. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Looking at the screenshot it seems the blue object isn't in a position to be hit. It looks like it's below the grid while the camera and ray are pointing along the z axis.
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    Doesn't it? Discounting what I said isn't helpful without answering the specifics of the question I asked.

    The code is trivial, I fully understand what you're trying to do. That wasn't what I was asking.

    If it's a Transform then this code makes no sense:
    Code (CSharp):
    1. Vector3 direction = otherObject - mainCamera.transform.position;
    If it's a Vector3 then this code makes no sense:
    Code (CSharp):
    1. if (hit.transform != otherObject)
    If "hitting" is defined by that method returning "true" then this makes no sense:
    Code (CSharp):
    1. if (hit.transform != otherObject)
    2. {
    3.     return true;
    4. }
    Just return the result of the Raycast without the logic as a test or attach a debugger i.e. debug it. Change the code to use Physics.Linecast temporarily to check you're not getting the direction wrong.
     
  8. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    It's going through it right in the center.
     
  9. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    Right, there is no hit at all, as I have of course tried without the logic first. It's how it works. Unfortunately, I'm getting no hit still. It's a puzzle!
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Keeping in mind ALL the stuff Melv says above, we know that the Unity 2D and 3D physics systems both work correctly.

    This means you are feeding into it something that is incorrect.

    No, it's a bug. This means it is time to you to start debugging!

    Here is how you can begin your exciting new debugging adventures:

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

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    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 names of the GameObjects or Components involved?
    - 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 supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

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

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    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

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
    Bunny83 likes this.
  11. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    Does it? If that planet is an actual sphere mesh, Debug.DrawRay by default has depthtest set to true. That means when it actually passes through an object, it would not be visible in the middle of the mesh. However we can see your lines all the way. So something seems to be off here.

    Since you use your "direction" variable in DrawRay, it would mean that the ray ends at the otherObject. So that essentially tells us that your otherObject is not that earth / sphere object, right? So you said you are sure the ray goes through that object, So I assume you have actually looked at the scene from different angles, right? You can hold ALT and right mouse button to orbit around the scene camera's focal point. You can select an object in the scene and press "f" to focus that object.

    As others have already mentioned. You are sure that:

    • your sphere object has a 3d collider most likely a SphereCollider? Note that 2d colliders do not work at all with the 3d physics system.
    • the collider size actually represents the object size? This is not necessarily the case. For Unity's default sphere that's usually true unless you tinkered with the size / center of the collider. You can usually see the actual collider shape in the sceneview when the object is selected. If not you either turned off the gizmos in the sceneview, or the collider doesn't have the right size / isn't there at all.
    • you have verified that the actual Physics.Raycast call returns false, so it never enters the if body. Try adding a log for both cases, hit and miss. One of the two has to happen. I've seen people tinkering with their script for hours just to realise that the ray they see didn't come from this script but from another one and this script wasn't attached at all and didn't run at all.
    • the positions of both the camera, the earh-like object and the otherObject are not at crazy large position values. Do not try to use real world numbers here. The floating point precision will cause all sorts of issues here. Though Unity should actually warn you about large position values, so pay attention to warnings in the console.
    • Note that the actual position of colliders are only updated during the internal physics update or when you call SyncTransforms manually. When you just adjusted the position of the collider, you can not directly raycast against that collider unless you call SyncTransforms in between.
     
  12. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    Just tried Physics.Linecast. It works perfectly. Thank you!
     
  13. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8

    Unfortunately it doesn't. It seems Raycast doesn't like "fast" moving objects. Replacing Raycast with Linecast seems to work just fine. Thank you for your post, I hope it helps someone!
     
  14. ferrinmass

    ferrinmass

    Joined:
    Jun 23, 2023
    Posts:
    8
    Yes it does. As stated above by MelvMay, I tried out Linecast instead of Raycast and everything now works as intended. Thanks!
     
  15. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Objects don't have "fast motion." Objects in a computer are simulated from one position to another.

    A raycast is instantaneous.

    If you raycast and something is there (and obviously you meet all the requirements) you will hit it.

    If it is going ten billion miles per hour you STILL will hit it as long as it is there at the moment you raycast.

    Everything just sits still in a computer until it is removed from one place and put in another place, which happens all at once per frame.
     
    Chubzdoomer, MelvMay and Bunny83 like this.
  16. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    That's not really possible as both, Raycast and Linecast do the exact same thing. However you provide different arguments. A raycast takes a start position, a direction vector and a max length which can even be infinite, which it is by default. A linecast has a start and an end position, that's the only difference. Have you actually read what Melv said? You should temporarily use a Linecast instead to see if you get your direction wrong. Maybe you have something else wrong, we don't know. Since your method is called "IsOtherObjectHidingBehindThatBlueSphereInTheImage" I guess you adapted your code to be posted here on the forum? Or do you really have a method that is named like that? I don't want you to reveal something that should be a secret for whatever reason. However if the code is not your actual code it becomes extremely difficult to actually address your problem.
     
    MelvMay likes this.