I wanted to share my camera controller modifications and get some feedback on the result. Here is a list to summarize what I did, and I will include the code for the class at the end of the post.
- Added some variables to the class, including some default zoom control values. I removed the const keyword so those values could be modified in the inspector. The naming convention could be refined a bit.
- Added a ResetDefaultZoomLevel() method that has a middle mouse button click control. I realize that as the course progresses I may need to remap that mouse control to a keyboard button.
- HandleZoom() modifies both the Y and Z axis of the targetFollowOffset, with both being based on the CURR_ZOOM_LEVEL variable.
- On the Virtual Camera, I set Aim > Tracked Object Offset > Y to 1.5.
- I also set the Virtual Camera’s Lens > Vertical FOV to 45, which is slightly different from the course instructions modification but could be set to your preference.
This setup creates more of a 3rd-person view as it lower’s the camera’s height when the view is centered on a unit. I haven’t yet decided where or how to implement a method that would center the camera behind a unit upon selection. Perhaps this feature gets added later in the course? I would love to hear any feedback on my code changes or how you feel about the way the zoom feels if you try implementing it.
Here is the class’s modified code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class CameraController : MonoBehaviour
{
[SerializeField]
private CinemachineVirtualCamera cinemachineVirtualCamera;
[SerializeField]
private float cameraMoveSpeed;
[SerializeField]
private float cameraRotationSpeed;
[SerializeField]
private float zoomSpeed = 5f; // not used in ResetDefaultZoomLevel() for snappier response
[SerializeField]
private int zoomIncrement = 2; // set to 1 for more granular control
[SerializeField]
private int defaultZoomLevel = 9;
[SerializeField]
private float zoomAngleFactor = 0.65f; // adjusts the slope/curve of the zoom motion. [ Y (camera height) = Z (camera distance) * zoomAngleFactor ] DO NOT set above 1.
[SerializeField]
private float CURR_ZOOM_LEVEL; // is set to match defaultZoomLevel in ResetDefaultZoomLevel(), which is called on Start()
[SerializeField]
private int MIN_CAM_ZOOM = 3;
[SerializeField]
private int MAX_CAM_ZOOM = 15;
private CinemachineTransposer cinemachineTransposer;
private Vector3 targetFollowOffset;
private void Start()
{
cinemachineTransposer = cinemachineVirtualCamera.GetCinemachineComponent<CinemachineTransposer>();
targetFollowOffset = cinemachineTransposer.m_FollowOffset;
ResetDefaultZoomLevel();
}
private void Update()
{
HandleMovement();
HandleRotation();
HandleZoom();
if (Input.GetMouseButton(2))
{
ResetDefaultZoomLevel();
}
}
private void HandleMovement()
{
Vector3 inputMoveDir = new Vector3(0, 0, 0);
if (Input.GetKey(KeyCode.W))
{
inputMoveDir.z = +1f;
}
if (Input.GetKey(KeyCode.S))
{
inputMoveDir.z = -1f;
}
if (Input.GetKey(KeyCode.A))
{
inputMoveDir.x = -1f;
}
if (Input.GetKey(KeyCode.D))
{
inputMoveDir.x = +1f;
}
Vector3 moveVector = transform.forward * inputMoveDir.z + transform.right * inputMoveDir.x;
transform.position += moveVector * cameraMoveSpeed * Time.deltaTime;
}
private void HandleRotation()
{
Vector3 rotationVector = new Vector3(0, 0, 0);
if (Input.GetKey(KeyCode.Q))
{
rotationVector.y = -1f;
}
if (Input.GetKey(KeyCode.E))
{
rotationVector.y = +1f;
}
transform.eulerAngles += rotationVector * cameraRotationSpeed * Time.deltaTime;
}
private void HandleZoom()
{
if (Input.mouseScrollDelta.y > 0)
{
CURR_ZOOM_LEVEL -= zoomIncrement;
}
if (Input.mouseScrollDelta.y < 0)
{
CURR_ZOOM_LEVEL += zoomIncrement;
}
CURR_ZOOM_LEVEL = Mathf.Clamp(CURR_ZOOM_LEVEL, MIN_CAM_ZOOM, MAX_CAM_ZOOM);
targetFollowOffset.z = -CURR_ZOOM_LEVEL;
targetFollowOffset.y = CURR_ZOOM_LEVEL * zoomAngleFactor;
cinemachineTransposer.m_FollowOffset = Vector3.Lerp(cinemachineTransposer.m_FollowOffset, targetFollowOffset, Time.deltaTime * zoomSpeed);
}
private void ResetDefaultZoomLevel()
{
targetFollowOffset.z = -defaultZoomLevel;
targetFollowOffset.y = defaultZoomLevel * zoomAngleFactor;
CURR_ZOOM_LEVEL = defaultZoomLevel;
cinemachineTransposer.m_FollowOffset = Vector3.Lerp(cinemachineTransposer.m_FollowOffset, targetFollowOffset, Time.deltaTime);
}
}