Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Raycast stops detecting colliders after a certain distance

Discussion in 'Physics' started by hummerbaendiger, Dec 19, 2018.

  1. hummerbaendiger

    hummerbaendiger

    Joined:
    Nov 28, 2012
    Posts:
    1
    Hi Everyone,

    I'm encountering the problem that the Physics.Raycast stops detecting colliders that are a certain distance away. (Unity 2018.2.11f1, iOS 12.1, ARKit 2.0)

    Background: I'm working on an app that uses ARKit on an iPad. In there small objects are moving around that have message boxes. Once you tap on one of the boxes, a more detailed message shows up. As Raycast targets I'm using simple sphere and box colliders.
    This should be proper way to do this in general, right? So far I didn't have any complications with that.

    Everything works fine as long as I'm close to the object to be tapped. But after a certain distance (~2m) the hit test simply doesn't detect the colliders anymore. The distance is a bit difficult to tell since the message boxes also scale a bit with the user. Nevertheless the colliders are always large enough to hit them with a finger comfortably.

    As a reference: here's the code used for ray casting which is pretty much the same as the sample that came with the ARKit Plugin demo scenes.
    Code (CSharp):
    1.  
    2. public class ARTouchHandler : MonoBehaviour {
    3.  
    4.     RaycastHit m_Hit;
    5.  
    6.     public UnityEvent Tapped;
    7.     Collider MyCollider;
    8.  
    9.     bool DoPhysicsRaycast(Touch touch, ref RaycastHit hitOut)
    10.     {
    11.         var ray = Camera.main.ScreenPointToRay(touch.position);
    12.         RaycastHit hit;
    13.         if (!Physics.Raycast(ray, out hit))
    14.             return false;
    15.  
    16.         hitOut = hit;
    17.         return true;
    18.     }
    19.  
    20.     void Start () {
    21.         MyCollider = GetComponent<Collider>();
    22.     }
    23.  
    24.     #if UNITY_EDITOR
    25.     Vector3 m_LastTouchPosition;
    26.     #endif
    27.  
    28.     Touch GetTouch()
    29.     {
    30.     #if UNITY_EDITOR
    31.         var touch = new Touch();
    32.         if (Input.GetMouseButtonDown(0))
    33.             touch.phase = TouchPhase.Began;
    34.         else if (Input.GetMouseButton(0) && m_LastTouchPosition != Input.mousePosition)
    35.             touch.phase = TouchPhase.Moved;
    36.         else
    37.             touch.phase = TouchPhase.Stationary;
    38.  
    39.         touch.position = Input.mousePosition;
    40.         m_LastTouchPosition = touch.position;
    41.         return touch;
    42.     #else
    43.             return Input.GetTouch(0);
    44.     #endif
    45.     }
    46.     void DoBegan(Touch touch)
    47.     {
    48.         if (Input.touchCount > 1)
    49.             return;
    50.  
    51.         if (DoPhysicsRaycast(touch, ref m_Hit))
    52.         {
    53.  
    54.             if (m_Hit.collider == MyCollider)
    55.             {
    56.                 Debug.Log("Hit " + this.gameObject.name);
    57.                 if (Tapped!=null) Tapped.Invoke();
    58.  
    59.             }
    60.         }
    61.     }
    62.     // Update is called once per frame
    63.     private void FixedUpdate()
    64.     {
    65.         if (Input.GetMouseButton(0) || (Input.touchCount > 0))
    66.         {
    67.             var touch = GetTouch();
    68.             switch (touch.phase)
    69.             {
    70.                 case TouchPhase.Began:
    71.                     DoBegan(touch);
    72.                     break;
    73.                 case TouchPhase.Moved:
    74.                     //DoMoved(touch);
    75.                     break;
    76.             }
    77.         }
    78.  
    79.     }
    80.  
    81.     void Update () {
    82.  
    83.  
    84.     }
    85. }
    86.  
    Having the scene running in the editor, I'm able to hit the colliders no matter how far away the camera is. For this I'm using the mouse input but pass the parameters along the same as with the native touch...

    What I tried so far:
    - equip the collider geometry with a kinematic rigid body - no success
    - scale the collider component's size and lower its game object scaling (in case the object gets optimized away if it's too small and too far away) and vice versa
    - Visualize the rays on the iPad to confirm that they actually intersect the colliders, which they do
    - Log to the console each time an object is hit with my DoPhysicsRaycast function, also the output shows only events when I'm close enough

    Is anybody aware of Unity or iOS doing some kind of collider optimization for smaller objects? And possibly how to avoid this?

    Thanks for your help :)
     
  2. I'm just wild guessing but you may have LODs? And maybe the smaller LOD levels don't have colliders on them? And In the editor you may always look at the objects on the scene view so they don't switch to other LOD levels?