I am trying to create a camera controller for an XCOM like tactical RPG. The main camera is the child of an empty gameObject (called “CameraController”), which is in the center of the camera’s view and is what is moved by player input. The player input is not directly received by the “CameraController” script, but by the “CameraControllerInput” script, which then passes that information to the “CameraController” script. The reason why the input has been separated from the CameraController script is so that later on, I can add different methods of player input (ie, touch screen controls) while keeping the CameraController functionality the same, and generally because it’s tidy.
Example screenshot: Imgur: The magic of the Internet
My current issue is with the zooming. What I want is when the player scrolls their mousewheel (or pinches the screen on their mobile phone), the main camera will either move towards or further away from the CameraController. I want to place restrictions on how far in and how far out the player can zoom the camera.
My first attempt at this was to simply transform.forward the Main Camera, but I wasn’t able to LERP that movement like the otherwise smooth movement of the Camera Controller.
The current way the zoom function works is that there is have another empty GameObject, called “CameraZoomDock”, pointed at a 45 degree angle towards the CameraController, that is moved forward and back by the mouse wheel (again, passed into the CameraZoomDock script from the CameraControllerInput script). The Main Camera is set to LERP to the CameraZoomDock, which makes for smooth movement. However, I am finding it difficult to set restrictions on how far the CameraZoomDock can move. I have tried mathf.clamping the CameraZoomDock’s Y and Z position (for example, the most you can zoom in should be X0, Y1, Z-1, and the futherest you can zoom out could be X0, Y10, Z-10, with the caps being able to be changed in the hierarchy). However, when I tried clamping the Y and the Z, the camera began bugging out and flying all over the place. I am not sure if the mathf.clamp is clamping the Y and Z position of the CameraZoomDock in relation to its parent gameObject, the CameraController. Is there a way to do this? I have searched Youtube videos and Unity forums, but I can’t find an answer to this solution.
EDIT: Thanks to metalted’s answer, I was able to get it to work! Here is the finished script for anyone interested:
CameraControllerInput
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControllerInput : MonoBehaviour
{
private CameraController _CameraController;
//mouse input
private float _mouseScroll = 0f;
void Start()
{
_CameraController = GetComponent<CameraController>();
//_CameraZoom = _MainCameraObject.GetComponent<CameraZoom>();
}
// Update is called once per frame
void Update()
{
//WASD and arrow key input for lateral camera movement.
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey("w"))
{
_CameraController.MoveCameraUp();
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey("s"))
{
_CameraController.MoveCameraDown();
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey("d"))
{
_CameraController.MoveCameraRight();
}
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey("a"))
{
_CameraController.MoveCameraLeft();
}
//"Q" and "E" key input for camera rotation.
if (Input.GetKeyDown("q"))
{
_CameraController.RotateCameraClockwise();
}
if (Input.GetKeyDown("e"))
{
_CameraController.RotateCameraCounterClockwise();
}
//mouse wheel input for camera zoom.
_mouseScroll = Input.GetAxis("Mouse ScrollWheel");
_CameraController.InputZoomValue(_mouseScroll);
}
}
CameraController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class CameraController : MonoBehaviour
{
public float _movementSpeed = 0.025f;
public float _movementTime = 5f;
public float _rotationAmount = 45f;
private float _mouseScroll = 0f;
//zoom values
public float _zoomSpeed = 10f;
public float _closestZoomDistance = -2f;
public float _furthestZoomDistance = -10f;
public float _smoothTime = 30f;
private Vector3 _newPosition;
private Quaternion _newRotation;
public GameObject _mainCameraObject;
private CameraZoom _CameraZoom;
private void Start()
{
_CameraZoom = _mainCameraObject.GetComponent<CameraZoom>();
_CameraZoom.setZoomValues(_zoomSpeed, _furthestZoomDistance, _closestZoomDistance, _smoothTime);
//in case a game designer accidentally pushes the camera out of the min/max distance boundaries,
// ... the camera will automatically be pushed within the boundaries on start up.
// So you won't get a situation where someone starts the game and the camera is stuck in the ground
float _tinyNumber = 0.0001f;
_CameraZoom.ZoomCamera(_tinyNumber);
_newPosition = transform.position;
_newRotation = transform.rotation;
}
void Update()
{
lerpCameraMovement();
}
public void InputZoomValue(float _inputMouseScroll)
{
_CameraZoom.ZoomCamera(_inputMouseScroll);
Debug.Log("Scroll = " + _inputMouseScroll);
}
// Moves the CameraController laterally.
public void MoveCameraUp()
{
{
_newPosition += (transform.forward * _movementSpeed);
}
}
public void MoveCameraDown()
{
{
_newPosition += (transform.forward * -_movementSpeed);
}
}
//rotate the camera around the cameraController in 45 degree intervals
public void MoveCameraRight()
{
{
_newPosition += (transform.right * _movementSpeed);
}
}
public void MoveCameraLeft()
{
{
_newPosition += (transform.right * -_movementSpeed);
}
}
// functions to rotate the CameraController.
public void RotateCameraClockwise()
{
_newRotation *= Quaternion.Euler(Vector3.up * _rotationAmount);
}
public void RotateCameraCounterClockwise()
{
_newRotation *= Quaternion.Euler(Vector3.up * -_rotationAmount);
}
void lerpCameraMovement()
{
//lateral camera movement lerping
transform.position = Vector3.Lerp(transform.position, _newPosition, Time.deltaTime * _movementTime);
//camera rotation lerping
transform.rotation = Quaternion.Lerp(transform.rotation, _newRotation, Time.deltaTime * _movementTime);
}
}
CameraZoom (alteration of metalted’s script)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour
{
private float _zoomSpeed = 0f;
private float _minimumZoomDistance = 0f;
private float _maximumZoomDistance = 0f;
private float _smoothTime = 0f;
private float _movePosition;
private float _smoothVelocity = 0;
private float _smoothMove;
public void Start()
{
_movePosition = transform.localPosition.z;
_smoothMove = _movePosition;
}
//the CameraController inputs values here.
//this way, the game designers only need to click on the CameraController gameobject and fiddle with the values in there
public void setZoomValues(float _inputZoomSpeed, float _inputMinimumZoomDistance, float _inputMaximumZoomDistance, float _inputSmoothTime)
{
_zoomSpeed = _inputZoomSpeed;
_minimumZoomDistance = _inputMinimumZoomDistance;
_maximumZoomDistance = _inputMaximumZoomDistance;
_smoothTime = _inputSmoothTime;
}
public void ZoomCamera(float _zoomInput)
{
if (_zoomInput != 0)
{
_movePosition += _zoomInput * _zoomSpeed;
_movePosition = Mathf.Clamp(_movePosition, _minimumZoomDistance, _maximumZoomDistance);
}
if (Mathf.Abs(_movePosition - _smoothMove) > 0.001f)
{
_smoothMove = Mathf.SmoothDamp(_smoothMove, _movePosition, ref _smoothVelocity, Time.deltaTime * _smoothTime);
Vector3 targetPosition = new Vector3(0, 0, _smoothMove);
transform.localPosition = targetPosition;
}
}
}