Juddering/jittering/stuttering raycast hit info - is it my Cinemachine?

EDIT: Problem solved, if you’ve come here with the same symptoms, check your player prefab for the Cinemachine Virtual Camera as it has Lens settings which are independent of the main camera. Make sure the Near Clip Plane setting in the Lens section isn’t too small. 0.5 works well for me.


Unity: 2021.3.0f1
Cinemachine: 2.8.4

I have Cinemachine set up as a 3rd person view on a player character using the Unity character controller as available on the Asset Store.

My player character can jump onto a moving platform in the 3D environment. This moving platform is a simple stretched cube with an additional collider added, used for detecting the player jumping on the platform. The platform has a simple script attached to it that moves it in a backward and forward motion, between two point 30 metres apart, by changing its own transform position during Update. When the player jumps on the platform, the player object is placed in the platform object hierarchy in order to automatically move with the platform.

My Cinemachine update method is late update.

When I Raycast from the main camera to the mouse position and place an object at the hit point, it’s rock solid.
When I do the same but the character is on the ground and the mouse pointer is on the moving platform, again it’s rock solid.

When my character is ON the platform, the first weird effect I was seeing was the placing of an object at the hit point was lagging behind what I was seeing on screen. I put this down to my Raycast happening before the camera had updated its position therefore Raycasting into a past position. In order to prove this, I put my script as the last in the Script Execution Order in my project configuration, and sure enough there is now no lagging position effect.

The problem I am now left with is that my hit point info returned seems to vary slightly on every frame. This leads to a severe juddering/jittering of the object I’m placing at the hit point.

I’m trying to wrap my head around this as it’s really confusing. The view on the screen is rock solid, the character moves exactly with the platform, the pointer doesn’t wander and the objects on the screen all appear rock solid. Even if I deliberately slow the frame rate down to 1fps, everything seems to move in sync except for the weird tiny variations I get at the hit point.

I keep wondering if Cinemachine has something to do with this but surely the camera can’t be moving so significantly that my hitpoint is varying?? Could it be a rounding problem?

I’m not a long term user of Unity, so any thoughts appreciated.

Also, I’m not sure I just want to push processing into fixed update when I don’t really understand why it isn’t working with normal update/lateupdate mechanisms. The platform is moved by position setting, as is the player, so there isn’t any rigid body physics being employed.

For reference, the test platform moves like this (after being instantiated at a hitpoint on a keypress):

public class MovePlatform : MonoBehaviour
{
    private Vector3 originalPos, currentTargetPos, finalPos;

    void Start()
    {
        originalPos = transform.position + new Vector3 (0,0.3f,0);
        finalPos = originalPos + new Vector3 (0,0,30);
        currentTargetPos = finalPos;
    }

    void Update ()
    {
        transform.position = Vector3.MoveTowards(transform.position, currentTargetPos, (10f * Time.deltaTime));

        if (Vector3.Distance(currentTargetPos, transform.position) <= 0)
            currentTargetPos = currentTargetPos == finalPos ? originalPos : finalPos;
    }

}

My positioning of the ‘cursor’ object looks like this and is called from LateUpdate in a script which is configured to run last in Script Execution Order. It just places a semi transparent disc at the hitpoint, orientated to the normal of the hitpoint.

private void Test ()
{
    RaycastHit hitData;
    Ray fromScreenRay = Camera.main.ScreenPointToRay(Input.mousePosition);
    bool gotPosition = Physics.Raycast(fromScreenRay, out hitData, 50, LocalPlayerMask);

    if (gotPosition)
    {
        targetCursor.transform.position = hitData.point + (hitData.normal * 0.02f);
        targetCursor.transform.rotation = Quaternion.LookRotation(hitData.normal);
    }
}
1 Like

Just to add a little more…

Debug logging the position of the camera whilst the player is on the platform shows it only moving in the z direction, which is correct as it’s following the player who is on a platform which is also only moving in the z direction.

Debug logging the position of the camera minus the position of the platform shows the camera isn’t deviating in the slightest in its position in relation to the platformed player/platform.

Which all makes me think it can’t be Cinemachine…although I only see the problem when Cinemachine is moving, even though Cinemachine isn’t deviating in position relative to the platform.

I think my head may explode…lol

Ok, so there’s something going on with ScreenPointToRay…

If I watch the mouse coordinates supplied to ScreenPointToRay (Input.mousePosition), they are rock solid (when I’m not moving the mouse obviously).

If I watch the coordinates of the camera, they are solid and only moving in Z plane at the same relative position to the thing the camera is looking at.

If I watch the raycast origin after the call to ScreenPointToRay, the origin x and y are jittering when I would have expected them to be solid, as the camera is solid.

The direction vector is also jittering but this is probably related to the origin point jitter?

Running a test with a fixed valid direction vector in the ray gives an almost solid result to the eye, but the debug figures show a little y direction jitter.

My camera near clipping plane is 0.1 but changing this to 1 doesn’t change the result. I’ve also tried creating the ray in the following way, but the result is the same.

Vector3 mousePos = Input.mousePosition;
Vector3 worldPos = Camera.main.ScreenToWorldPoint( new Vector3(mousePos.x, mousePos.y, 1) );
Vector3 camPos = Camera.main.transform.position;
fromScreenRay.origin = camPos;
fromScreenRay.direction = ( worldPos - camPos ).normalized;

Now scratching my head and thinking there’s something going on under the hood that I haven’t understood…

Creating a ray in the following way produces a rock solid hit point, albeit fixed to the middle of the screen.

fromScreenRay = new Ray(Camera.main.transform.position, Camera.main.transform.forward);

After all the testing, I don’t think this problem is related to Cinemachine so I’m going to reframe what I’ve found in one of the other forums and see if anyone has experience with the problem.

Thanks everyone that took the time to read this thread.

Problem solved, see first post for info.

2 Likes