[SOLVED]Raycasted mouse-follow-object jittering when rotating camera

(Solution at bottom)

I have a camera with 2 scripts on it.

the mouse rotation script and a “building script” that does instantiate an object and let it follow the mouseposition (and place it, but thats not necessery here).

the part i dont understand is when i turn the rotation script off so that i have a fixed camera, the building script works well and i dont see any jittering/stuttering or whatever when i move the mouse with the object - even when close to the camera everything works fine.

when the rotate script is on im encountering an ugly jittering on the object when moving the mouse with it.

Fullscreen GIF:
https://giphy.com/gifs/mk7qW316Yheqilobuq/fullscreen

i googled ALOT and didnt find any solution this while i guess is not that hard…i printed the hit.point and it looked like there was a jitter…
what i already tried that made it worse or didnt help:

  • Replace Update with FixedUpdate and check input events in Update method separately
  • add a Vector3.Lerp (you can see it in code…that was horrible…like a smooth jittering oO)

i just cant fix it…and i already tried different rotate controllers like first person starter asset where i first encountered this problem…
definitely has something to do with the rotation…
any help appreciated :slight_smile:

rotate script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseLook : MonoBehaviour
{
    public float mouseSensitivity = 100f;
    public Transform playerBody;

    float xRotation = 0f;
    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

   
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);

        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
        playerBody.Rotate(Vector3.up * mouseX);
        
    }
}

building script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RTSBuildingSystem : MonoBehaviour
{
    [SerializeField]
    private GameObject _placeholderBuilding;
    private GameObject _placeholder;

    private LayerMask layer = 3;

    [SerializeField]
    private GameObject _building;

    private Vector3 _mousePosition;
    private float _previousX;
    private float _previousZ;
    private float rotSpeed = 25f;

    private Building _buildingScript;

    public bool buildingMode;

    private void Start()
    {
        
    }

    
    private void Update()
    {

        if (Input.GetKeyDown("q"))
        {
            if (buildingMode) 
            {
            
                 buildingMode = false;
                 Debug.Log("BUILD OFF");
                 Destroy(_placeholder);
            }
            else
            {
                 buildingMode = true;
                 Debug.Log("BUILD ON");
                _placeholder = Instantiate(_placeholderBuilding);
                _buildingScript = _placeholder.GetComponent<Building>();
               
            }
        }
        


        if (buildingMode)
        {

            _mousePosition = Input.mousePosition;

            Ray ray = Camera.main.ScreenPointToRay(_mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, Mathf.Infinity, layer))
            {
                float positionX = hit.point.x;
                float positionZ = hit.point.z;

                float rot = Input.GetAxis("Mouse ScrollWheel") * rotSpeed;

                _placeholder.transform.Rotate(0f, rot, 0f, Space.Self);
                


                if (_previousX != positionX || _previousZ != positionZ)
                {
                    _previousX = positionX;
                    _previousZ = positionZ;

                    _placeholder.transform.position = new Vector3(positionX, 0f, positionZ);
                   // _placeholder.transform.position = Vector3.Lerp(_placeholder.transform.position, new Vector3(positionX, 0f, positionZ), 0.07F);
                }

                if (Input.GetMouseButtonUp(0))
                {
                    if (_buildingScript.isBuildable)
                        Instantiate(_building, _placeholder.transform.position, _placeholder.transform.rotation);
                }




            }
        }


    }

------EDIT: FOUND THE SOLUTION-----

Somehow it was the Cursor.lockState = CursorLockMode.Locked;

Since i do the Raycast with Ray ray = Camera.main.ScreenPointToRay(_mousePosition); the _mousePosition is defined be the Cursor.lockState = CursorLockMode.Locked; which binds the mousepoint to the middle of the screen (and hiding it).
I dont know why but this build-in function causes the jitter…
A workaround i found is not to rely on mouse position and get the “middle of-the-screen-point” in a different way for doing the raycast:

Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));

Thats it.

It might be possible while RotationScript is active, your ScreenToWorldPoint is jumping to recalculate the values. Basically mousePosition + mousePosition might be equaling 2 times the amount. While placing the build, you might wanna lock camera rotation, and only allow W,A,S,D for camera movement.