Search code examples
c#unity-game-enginecameracontrolsright-mouse-button

Unity C#: Camera Control Using Automatic Positioning & Mouse Look


I don't usually post here but it has taken me hours now trying to figure this out and I've searched the net already but couldn't find the answer. I'm wishing someone might be able to assist me here. I'm a newbie and this is the first time I'm trying to combine two types of Third Person Camera Control that follows the Players movement in Unity C#:

  1. Camera Snaps to a pre-defined Position and Rotation as the Player Moves (No Mouse Look)
  2. Mouse Look activates when a Mouse Button is held down and so the Camera rotates according to Mouse movement whether the Player's Position is changing or not

It almost works except that I cannot seem to reset the Mouse Look to its first ever pre-defined setting. After the Player releases the Mouse Button, the code for #1 kicks in and so the Camera seem to go back to its default view. But doing further Mouse Looks, I noticed the Camera always returns to the last position & rotation it was deactivated. I need it to go back to the original pre-defined position & rotation even before the Player activates his first Mouse Look so its not too disorienting for the Player.

I tried several codes but couldn't get it to work so I removed non working lines and just posted those that I think are applicable ones. Please refer to my code below. Would appreciate it if someone can help me. Thanks in advance!

Edit: Updated the code to have two methods of controlling the Camera and added suggested code to reset the currentX & Y values. Comment/uncomment each of the method call to test. But I still have the problem of not being able to smooth out the zooming of the mouse look.

Final Edit: I have again updated the code below, cleaned it up, and included the suggested changes. Code should now be fully working and has no jitters. Thanks for the assistance! :-)

Last Final Edit: Added "Field of View Zooming" by Mouse Wheel and so have completed the code.

using UnityEngine;
using System.Collections;

public class PlayerViewController : MonoBehaviour {

    // General Vars
    public Transform targetFollow;
    private bool lookAround = false;

    // For SmoothDampFollow
    public Vector3 followDefaultDistance = new Vector3 (0f, 12.0f, -20f);
    public float followDistanceDamp = 0.2f;
    public Vector3 followVelocity = Vector3.one;

    // For Camera Orbit
    public float orbitDistance = 20.0f;
    public float orbitDamp = 5.0f;
    private const float angleMinY = 7.0f;
    private const float angleMaxY = 50.0f;    
    private float currentX = 7.0f;
    private float currentY = 50.0f;

    // For Zooming Field Of View
    public float FOVmin = 50.0f;
    public float FOVmax = 100.0f;
    public float mouseWheelSpeed = 5.0f;

    void Update () {

        if (Input.GetMouseButtonDown (1)) {

            currentX = transform.eulerAngles.y;
            currentY = transform.eulerAngles.x;

        }

        if (Input.GetMouseButton (1)) {

            lookAround = true;

        } else {

            lookAround = false;

        }

        ZoomFOV ();

    }

    void FixedUpdate () {

        if (lookAround) {

            CameraOrbit ();

        } else {

            SmoothDampFollow ();

        }

    }

    void ZoomFOV () {

        if (Input.GetAxis ("Mouse ScrollWheel") > 0) {

            GetComponent<Camera> ().fieldOfView =  GetComponent<Camera> ().fieldOfView - mouseWheelSpeed;

            if (GetComponent<Camera> ().fieldOfView <= FOVmin) { GetComponent<Camera> ().fieldOfView = FOVmin; }

        } else if (Input.GetAxis ("Mouse ScrollWheel") < 0) {

            GetComponent<Camera> ().fieldOfView = GetComponent<Camera> ().fieldOfView + mouseWheelSpeed;

            if (GetComponent<Camera> ().fieldOfView >= FOVmax) { GetComponent<Camera> ().fieldOfView = FOVmax; }

        }

    }

    void SmoothDampFollow () {

        if (!targetFollow) {

            return;

        } else {

            Vector3 wantedPosition = targetFollow.position + (targetFollow.rotation * followDefaultDistance);
            transform.position = Vector3.SmoothDamp (transform.position, wantedPosition, ref followVelocity, followDistanceDamp);
            transform.LookAt (targetFollow, targetFollow.up);

        }

    }

    void CameraOrbit () {

        if (!targetFollow) {

            return;

        } else {

            currentX += Input.GetAxis ("Mouse X");
            currentY += Input.GetAxis ("Mouse Y");
            currentY = Mathf.Clamp (currentY, angleMinY, angleMaxY);
            Vector3 dir = new Vector3 (0, 0, -orbitDistance);
            Quaternion rotation = Quaternion.Euler (currentY, currentX, 0);
            Vector3 wantedPosition = targetFollow.position + rotation * dir;
            transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * orbitDamp);
            transform.LookAt (targetFollow.position);

        }

    }

}

Solution

  • Updated: Try this

    void LateUpdate()
    {
    
        if (lookAround)
        {
    
            currentX += Input.GetAxisRaw("Mouse X");
            currentY += Input.GetAxisRaw("Mouse Y");
            currentY = Mathf.Clamp(currentY, angleMinY, angleMaxY);
            Vector3 dir = new Vector3(0, 0, -distance);
            Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
    
            Vector3 wantedPosition = target.position + rotation * dir;
            transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
    
            camTransform.LookAt(target.position);
    
        }
            ...
    

    And

    void Update()
    {
        // Here
        if (Input.GetMouseButtonDown(1))
        {
            currentX = transform.eulerAngles.y;
            currentY = transform.eulerAngles.x;
        }
        if (Input.GetMouseButton(1))
        { 
            ...
    

    What i've done is i reset the currentX and currentY to their current eulerangle-values on mouse-press in Update(). And i've added a position Lerp to the wanted lookAround position in LateUpdate()

    EDIT:

    Though I still haven't fixed the smooth zooming of the mouse look when right mouse button is initially held down

    Try this change

    void CameraOrbit()
    {
        currentX += Input.GetAxisRaw("Mouse X");
        currentY += Input.GetAxisRaw("Mouse Y");
        currentY = Mathf.Clamp(currentY, angleMinY, angleMaxY);
        Vector3 dir = new Vector3(0, 0, -distance);
        Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
    
        // -->
        Vector3 wantedPosition = target.position + rotation * dir;
        transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
        // <--
    
        camTransform.LookAt(target.position);
    }