Search Unity

Free Look camera and mouse responsiveness

Discussion in 'Cinemachine' started by Eudaimonium, Mar 11, 2019.

  1. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    Hi,

    I am using Cinemachine Free Look rig to control an over-the-shoulder third person character. I love Cinemachine's features but I found the responsiveness to mouse input to be very bad.

    Default settings of the X and Y axis controls simply limit the maximum camera movement to something very low - basically if you move the mouse really fast, the camera moved a disproportionally small amount. It's a simulated "negative acceleration" akin to bad PC ports where mouse is basically an emulated analogue stick.

    Raising the "Max Speed" of the axis controls also raises the "sensitivity" of the camera for some reason, so the value multipliers in the Input Manager need to be lowered drastically. This doesn't really fix the problem, and also introduces incredible camera jerkiness when Editor drops frames and delta time spikes up (very frequent with complex inspectors or custom editor windows present).

    In short, how can I use the features of the Freelook camera rig (I love the top-mid-bottom rig and obstacle avoidance), but preserving the 1:1 native mouse input as we've all come to expect from PC games?

    EDIT:
    Side note - Camera Collider doesn't work well with Camera Offset - it appears collider is always applied first regardless of script order, resulting in camera clipping through walls anyway.
     
    Last edited: Mar 11, 2019
  2. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    Bump. Nobody else has mouse responsiveness problems when using Cinemachine Free Look?

    I can produce examples/videos to demonstrate the problem if needed.
     
  3. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Getting a good response is about tuning the numbers - both max speed and accel/decel times. Can you post the values you're using? A picture of the inspector would be helpful.

    If you can't tune the numbers to your satisfaction, you can always write your own custom Axis value manipulator. Just set the Input Axis Name to blank, and drive Axis.Value the way you want.

    This is because the Collider offset is applied after the camera Body position is calculated, but the Camera offset is applied after the Aim has been calculated, because the offset is in Camera space. Script order will only affect the order within the pipeline category (e.g. Aim or Body).

    If you don't mind the camera offset being relative to the target's orientation (as opposed to the Camera's orientation), you could try to make a custom version of the CameraOffset that makes its calculation during the Body stage (it would have to interpret the offset relative to the target's orientation or in world space, but maybe that's ok for your application). Then, you could order the extensions to put the offset before the collider.

    To make a custom extension, just copy the original from the CM package into your Assets, rename it, and modify it. It will appear automatically in the Extensions dropdown.
     
  4. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    These are my values:
    upload_2019-3-13_16-40-23.png

    The axis value multiplier in Input Manager is 0.01 to achieve normal responsiveness, but I'm still not happy with this. I would like the "maximum" speed to be effectively unlimited, and not affect the sensitivity (Warframe has exceptional mouse responsiveness in a third person camera, for example).

    I would very much like to manually drive the axis values - how do I do this? I couldn't find anything in the documentation.
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Try putting non-zero values in the accel and decel. Something very small, less than 0.1. Values too close to 0 tend to produce jerky motion (this is a known issue).

    To drive the values yourself, start by setting the Input Axis Name values to blank. This disables the automatic querying of the input system for the input values. Disable recentering as well, and then CM will never try to change the axis values. Then, attach a custom script to drive freeLook.m_xAxys.Value and freeLook.m_YAxis.Value. Just set it in Update to the value you want. X axis ranges from -180 to +180, and Y axis ranges from 0 to 1.
     
  6. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    I'll give it a go later today. Thank you very much for your time and help!
     
  7. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    I did it. Recalculating the mouse input values into axis values was a lot easier than I thought.

    For any future Google travellers looking to get 1:1 mouse responsiveness out of your Cinemachine Free Look, first of all hi! I hope Anthem is better now! Second, here, slap this into the virtual camera with Free Look script on it:

    Code (CSharp):
    1.  
    2. using Cinemachine;
    3. using UnityEngine;
    4.  
    5. public class CinemachineManualFreeLook : MonoBehaviour
    6. {
    7.     private CinemachineFreeLook freeLook;
    8.  
    9.     public float horizontalAimingSpeed = 20f;
    10.     public float verticalAimingSpeed = 20f;
    11.  
    12.     [Tooltip("This depends on your Free Look rigs setup, use to correct Y sensitivity,"
    13.         + " about 1.5 - 2 results in good Y-X square responsiveness")]
    14.     public float yCorrection = 2f;
    15.  
    16.     private float xAxisValue;
    17.     private float yAxisValue;
    18.  
    19.     private void Awake()
    20.     {
    21.         freeLook = GetComponent<CinemachineFreeLook>();
    22.     }
    23.  
    24.     private void Update()
    25.     {
    26.         float mouseX = Input.GetAxis("Mouse X") * horizontalAimingSpeed * Time.deltaTime;
    27.         float mouseY = Input.GetAxis("Mouse Y") * verticalAimingSpeed * Time.deltaTime;
    28.  
    29.         // Correction for Y
    30.         mouseY /= 360f;
    31.         mouseY *= yCorrection;
    32.  
    33.         xAxisValue += mouseX;
    34.         yAxisValue = Mathf.Clamp01(yAxisValue - mouseY);
    35.  
    36.         freeLook.m_XAxis.Value = xAxisValue;
    37.         freeLook.m_YAxis.Value = yAxisValue;
    38.     }
    39. }
    40.  

    Pastebin link for convenience:
    https://pastebin.com/ryGiyMhb
     
    rshea0, filod and Gregoryl like this.
  8. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    Resurrecting the thread in favor of opening a new one;

    How do I go about that?

    I made a copy of the Offset script, it's recognized nicely. Changing the Stage bit to Body obviously messes up the math.
    This doesn't appear to work correctly:
    Code (CSharp):
    1. protected override void PostPipelineStageCallback(
    2.         CinemachineVirtualCameraBase vcam,
    3.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    4.     {
    5.         if (stage == CinemachineCore.Stage.Body)
    6.         {
    7.             Vector3 offset = transform.localToWorldMatrix * m_Offset;
    8.             state.ReferenceLookAt += offset;
    9.             state.PositionCorrection += offset;
    10.         }
    11.     }
    How do I correctly offset the camera during Body stage?
     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    One thing: you're calculating the offset in camera-space, using transform.localToWorldMatrix. You should be using the target's localToWorld, because in the Body stage the camera hasn't yet been rotated to its final orientation, but the target has.
     
  10. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    What is the camera target within this scope? vcam.Follow and vcam.LookAt give me the same result.
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Generally camera position relates to what you're following, so I'd use that.
     
  12. Parappa2

    Parappa2

    Joined:
    Sep 9, 2016
    Posts:
    12
    When using Eudaimonium's 1:1 free look script you have to set max speed, accell and decell of both y and x axis to 0.
    Also attach the script to the top of the virtual camera, above the "Cinemachine Free Look (Script)", to get smooth movement

    edit:it still doesnt work, move speed is limited when moving the mouse very fast. And sometimes its jittery when starting the game.I will have to try some other solution
     
    Last edited: Apr 11, 2019
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    It looks like Eudaimonium's script is more tailored for joystick than mouse.

    Here is an alternative script that you can use instead. It drives the FreeLook's axes in a nice 1:1 way. Add it to your FreeLook object to replace the FreeLook's default axis behaviour.
     

    Attached Files:

    Last edited: Apr 15, 2019
    rshea0 and amanchatterjee121 like this.
  14. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    Incorrect, I use it exclusively for mouse input, I can feel no artificial damping or upper speed limiting in my controls. it just "feels" right. The whole "offset over the shoulder" thing is another can of worms, though, but as for the responsiveness itself, it's what I set out to do.

    Parappa2, are you sure you removed the strings from the "Input Axis Name" fields in the Free Look script? My script assumes those are blank, so the axis values are driven externally. Gregoryl's script explicitly clears those fields on Awake, though. I should've probably done that.
     
  15. Parappa2

    Parappa2

    Joined:
    Sep 9, 2016
    Posts:
    12
    no i didnt do that
     
  16. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    Yeah I definitely should've mentioned that :confused:

    Give it a shot, see if it works then.
     
  17. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    @Eudaimonium using your script finally cinemachine feels responsive.
    I don't get it why cinemachine doesn't have this kind of input mode built in :/
    Thanks a lot man.
     
    Eudaimonium likes this.
  18. Exbleative

    Exbleative

    Joined:
    Jan 26, 2014
    Posts:
    216
    Big +1 from me, I feel like the default input/control on Cinemachine's virtual cameras is fine for something like a controller, but feels laggy and insensitive with the mouse. Surprised there aren't more people making FPS saying the same thing.

    Have noticed this as well. Seems like 0.1 is almost the only value to use here. Smaller gets jerkier, over 0.1 gets laggier.
     
  19. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    And we agree with you. The existing Axis input is optimized for joystick-type controllers, and is not so great for mouse input.

    The latest CM 2.3.5 (available in preview) has the requested mode built in. Set the speed mode as follows, and you'll get a more mouse-appropriate response:

    upload_2019-8-26_10-47-42.png

    The new mode also behaves well with 0 accel/decel time.
     
  20. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Finally!!! Thank you for adding this to CM
     
  21. Eudaimonium

    Eudaimonium

    Joined:
    Dec 22, 2013
    Posts:
    131
    I guess better late than never, but here's my custom camera collider which works with the whole "over the shoulder but slightly offset to the side third person camera" thing. I've basically gutted the built-in collider and made it use one sphere cast instead of many MANY raycasts it normally uses.
     

    Attached Files:

  22. smdanjm

    smdanjm

    Joined:
    Sep 10, 2020
    Posts:
    1
    Hey Gregoryl,
    How does one dynamically switch between Input Value Gain mode and Max Speed mode if they want to have both controller or mouse input options in the final product? Due to the time-dependent nature of Max Speed mode and time-independence of Input Value Gain, I am experiencing framerate dependence with controller input.
     
  23. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    You'll have to write code to switch the value directly in the CM components.
     
  24. sevan98t

    sevan98t

    Joined:
    Mar 31, 2020
    Posts:
    3
    @Gregoryl This code is great Thanks. :) And if you have any good code or setup for Offset X Top-Mid-Bottom Rig that makes character is little bit offseted to the left can you share please ? I did some setup by myself but i did not get a great result. And one more thing how can i make zoom out and zoom in(without FOV).
    Thanks . :)
     
    Last edited: May 13, 2021
  25. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    @sevan98t There is the CinemachineCameraOffset extension, you can just use it. However, this does not play well with the CinemachineCollider.

    If you are trying to make a 3rdPerson camera, there are alternatives to FreeLook which are better suited to the task. In particular, have a look at the AimingRig sample, and at this tutorial video:

     
  26. sevan98t

    sevan98t

    Joined:
    Mar 31, 2020
    Posts:
    3
    @Gregoryl Hi, I already watched that video.But this camera doesn't have x y rotation with mouse. It always rotates with player. So i created a new gameobject and set position to my character position on update .I made the 3rdPerson camera follow that gameobject and now it doesn't rotates with my player, and then i merged your code("FreeLookAxisDriver) with the camera. As a result i got exactly what I wanted perfectly. Now i can aim(zoom) perfectly with saving aim position (which i cant do this with freeLookCamera ), rotate around player with mouse(X,Y) and follow the player.

    Thank you very much again. Your code helped me so much. :)
     
    Gregoryl likes this.
  27. TerranRich

    TerranRich

    Joined:
    May 7, 2018
    Posts:
    5
    Hi there. Do you have a version of this script that works with Unity's new Input system? I tried myself, but there's too much going on in that script for somebody like myself to alter.

    Also, changing "Max Speed" to "Input Value Gain" does not give the desired results. I still don't understand why Cinemachine doesn't handle like a normal gaming camera out-of-box.
     
  28. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    What's wrong with it?
     
  29. timmccune

    timmccune

    Joined:
    Sep 27, 2018
    Posts:
    29
    I was having some jerky movement from mouse with the CM_Freelook cam and the new input system. I was able to resolve it by adding the "Cinemachine Input Provider" with the appropriate MouseLook Action in the XY Axis field, Setting the CM_Freelook Axis controls: both to Input Value Gain and a much lower speed settings. In my Input Action: MouseLook(Vector2 Passthrough) with 2 bindings: Right Stick [Gamepad] and Mouse(Delta) with a normalize Vector2 Processor. Both the gamepad and mouse are working pretty well. Hope this helps someone.
     
    dkamp and Gregoryl like this.
  30. Chregu

    Chregu

    Joined:
    Jan 7, 2018
    Posts:
    3
    I have the problem that Input Value Gain seems to be framerate dependent. Setting the speed at 60fps and then changing the fps to 30 will result in way faster input speed. Also at very high framerates the camera gets very slow and also seems to stutter (doesn't recognize movement).
     
  31. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,728
    Two questions:
    1. What version of CM?
    2. Is your vcam updating on FixedUpdate or LateUpdate?