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

Raycast jittery behaviour on long distances

Discussion in 'Scripting' started by LaserRock, Nov 23, 2020.

  1. LaserRock

    LaserRock

    Joined:
    Jan 2, 2018
    Posts:
    11
    This video shows my problem with jittery raycast on long distance and perspective camera. This problem do not occurs while camera is set in orthographic mode.
    In the first part of the video, while zooming out I'm shooting raycast using Camera.ScreenPointToRay() and this causes this jittery effect. In the second part of the video I'm switching to mode that uses transform as a raycast source and problem disappear.
    Video link: https://drive.google.com/file/d/1a1Qa08uVEWwQCaChYX6Yow18dh0_2lw1/view?usp=sharing
    Code:
    Code (CSharp):
    1. //raycast from transform (works fine, workaround solution)
    2.         if (rayMode)
    3.         {
    4.             float verticalFov = Camera.HorizontalToVerticalFieldOfView(_fieldOfView, _camera.aspect);
    5.             float screenHeightL = Mathf.InverseLerp(0, Screen.height, InputSingleton.Instance.inputActions.Player.MousePosition.ReadValue<Vector2>().y);
    6.             float screenWidthL = Mathf.InverseLerp(0, Screen.width, InputSingleton.Instance.inputActions.Player.MousePosition.ReadValue<Vector2>().x);
    7.             float yRot = Mathf.Lerp(-_fieldOfView / 2, _fieldOfView / 2, screenWidthL);
    8.             float xRot = Mathf.Lerp(verticalFov / 2, -verticalFov / 2, screenHeightL);
    9.             _raycastTransform.localEulerAngles = new Vector3(xRot, yRot, 0);
    10.             if (Physics.Raycast(_raycastTransform.position, _raycastTransform.forward, out RaycastHit hit, Mathf.Infinity, _raycastTarget))
    11.             {
    12.                 _prevRaycastPosition = hit.point;
    13.                 if (_prevRaycastPosition != _raycastPosition)
    14.                 {
    15.                     _raycastPosition = hit.point;
    16.                     _raycastHitGO = hit.collider.gameObject;
    17.                  
    18.                     FunctionUpdateSwitch();
    19.                     _bendController.UpdateBend(_raycastPosition);
    20.                     BezierUpdate();
    21.                     _trackAnalyzer.Update();
    22.                 }
    23.             }
    24.         }
    25.         //raycast from camera (jitter)
    26.         else
    27.         {
    28.             Ray ray = _camera.ScreenPointToRay(InputSingleton.Instance.inputActions.Player.MousePosition.ReadValue<Vector2>(), Camera.MonoOrStereoscopicEye.Mono);
    29.             if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, _raycastTarget))
    30.             {
    31.                 _prevRaycastPosition = hit.point;
    32.                 if (_prevRaycastPosition != _raycastPosition)
    33.                 {
    34.                     _raycastPosition = hit.point;
    35.                     _raycastHitGO = hit.collider.gameObject;
    36.                  
    37.                     FunctionUpdateSwitch();
    38.                     _bendController.UpdateBend(_raycastPosition);
    39.                     BezierUpdate();
    40.                     _trackAnalyzer.Update();
    41.                 }
    42.             }
    43.         }
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Approximately how far is this "long distance"? From a quick look at the video it might just be floating point inaccuracy.
     
  3. LaserRock

    LaserRock

    Joined:
    Jan 2, 2018
    Posts:
    11
    200-900 units
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    My guess is highly unlikely then.
     
  5. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    656
    Could be due to when the camera updates its position compared to when your script updates the line. Try putting your code in LateUpdate instead... (Or use Script execution order to control which Update is run when...
     
    Joe-Censored likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    At fine grain resolutions the mouse input could be noisy, especially when zoomed out and a 1-pixel mouse change is actually a much-larger world change.

    One way to fix that is to time-filter the mouse position (such as time-weighted average, or just using Lerp), or else don't move it unless it gets far enough away from the last position.

    In that case you'd have a separate Vector2 of where the mouse is, and you would move that position towards where the mouse presently is, but perhaps only once it becomes larger than 2 pixels away, for instance.
     
    Joe-Censored likes this.
  7. LaserRock

    LaserRock

    Joined:
    Jan 2, 2018
    Posts:
    11
    I found the solution. Cemera near clip plane was set to ultra low value like 0.001f and after changing it to 0.01 the problem has gone.
     
  8. tomph

    tomph

    Joined:
    Nov 6, 2013
    Posts:
    33
    Maaaaan, this bug hit hard (wasted a whole day). Your solution worked @LaserRock , thank you for sharing!
     
  9. mzlafty

    mzlafty

    Joined:
    Jan 20, 2020
    Posts:
    3