Camera Snapping when trying to rotate player

This may be stupid, but I’m new to this…
I linked a video down below showing my problem, but basically I want to rotate my ‘player’ (Just a cube) when I am holding down the right mouse button, and it works well after I hold it down.

The issue is that if I just right click on the screen it jumps around, and i’m not sure what is causing it. I’m sure it’s something easy that I just don’t know about and don’t know where to look. Any help would be very much appriciated!

CODE:

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


public class PlayerController : MonoBehaviour
{

    [SerializeField] private float speed, lookSensitivity;

    private float totalXRotation;
    private float totalYRotation;

    private PlayerActionControls playerActionControls;

    private void Awake(){
        playerActionControls = new PlayerActionControls();
    }

    private void OnEnable(){
        playerActionControls.Enable();
    }

    private void OnDisable(){
        playerActionControls.Disable();
    }

    void Start()
    {
       
    }

    void Update()
    {
        //Read the movement value
        float movementInput = playerActionControls.FreeForm.Move.ReadValue<float>();
        float mouseRightInput = playerActionControls.FreeForm.MouseButtons.ReadValue<float>();

        //Move the player
        Vector3 currentPosition = transform.position;
        currentPosition.x += movementInput * speed * Time.deltaTime; //Left|Right Movement
        transform.position = currentPosition;

        totalXRotation += Mouse.current.delta.x.ReadValue() * lookSensitivity;
        totalYRotation += Mouse.current.delta.y.ReadValue() * lookSensitivity;

        if(mouseRightInput == 1){ //If the Right mouse button is held
            //Get the mouse position
            Debug.Log("Mouse X Rotation: " + totalYRotation + " Mouse Y Rotation: " + totalXRotation);
            transform.rotation = Quaternion.Euler(-totalYRotation, totalXRotation, 0f);
        }
       
    }
}

You need to “back out” the zeropoint of where the mouse went down.

So basically on the moment the mouse goes down:

  • write down the current mouse position as “zero”

On every frame:

  • if mouse held down, read the mouse and subtract the zero.

Use the resulting amount (which is the difference since the mouse went down) everywhere.


EDIT: let me restate what I had written above, since your setup is slightly different:

Regardless of mouse state, you are updating rotations.

Then when the click goes down, you are DRIVING it right there.

By that point the rotations have changed a lot.

I think if you want click-hold-to-drag, do not update the rotations unless the button is down.

1 Like

I feel so stupid. Thank you so much for the fresh perspective. All I did to fix this was move 2 lines of code.
From this:

void Update()
    {
        //Read the movement value
        float movementInput = playerActionControls.FreeForm.Move.ReadValue<float>();
        float mouseRightInput = playerActionControls.FreeForm.MouseButtons.ReadValue<float>();
        //Move the player
        Vector3 currentPosition = transform.position;
        currentPosition.x += movementInput * speed * Time.deltaTime; //Left|Right Movement
        transform.position = currentPosition;

        totalXRotation += Mouse.current.delta.x.ReadValue() * lookSensitivity;
        totalYRotation += Mouse.current.delta.y.ReadValue() * lookSensitivity;

        if(mouseRightInput == 1){ //If the Right mouse button is held
            //Get the mouse position
            Debug.Log("Mouse X Rotation: " + totalYRotation + " Mouse Y Rotation: " + totalXRotation);
            transform.rotation = Quaternion.Euler(-totalYRotation, totalXRotation, 0f);
        }
     
    }

To this:

void Update()
    {
        //Read the movement value
        float movementInput = playerActionControls.FreeForm.Move.ReadValue<float>();
        float mouseRightInput = playerActionControls.FreeForm.MouseButtons.ReadValue<float>();

        //Move the player
        Vector3 currentPosition = transform.position;
        currentPosition.x += movementInput * speed * Time.deltaTime; //Left|Right Movement
        transform.position = currentPosition;

        if(mouseRightInput == 1){ //If the Right mouse button is held
            //Get the mouse position
            totalXRotation += Mouse.current.delta.x.ReadValue() * lookSensitivity;
            totalYRotation += Mouse.current.delta.y.ReadValue() * lookSensitivity;

            Debug.Log("Mouse X Rotation: " + totalYRotation + " Mouse Y Rotation: " + totalXRotation);
            transform.rotation = Quaternion.Euler(-totalYRotation, totalXRotation, 0f);
        }
      
    }

To this:

1 Like

Not at all… staring at code can be baffling even in the simplest of cases. You just steadily get better and better at it. I’ve just seen a few more lines of code than you, that’s all!!

Let me offer you this “standard blurb” that I tell people to use whenever code is giving them trouble, such as the above. The following technique can help you understand 100% of ALL problems. It is a universal approach.

Here it is:

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

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 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 put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

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

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

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://discussions.unity.com/t/839300/3

Just to assure you this happens all the time even for experienced programmers, as Kurt-Dekker has pointed out you can put debug log or make use of print if you want to experiment with things like execution order and how the void functions operate. It’s a good way to learn the quirks of the engine very quickly without going into a complicated project and not understanding what’s going on.

This will be much further down the line but for learning general optimisation techniques for your code I recommend learning about the Unity Profiler, it’s very handy and combining that with a good knowledge of execution order will let you write very efficient code every time.

1 Like