- Home /
Trying to restrict the distance the player can zoom a 3D camera (not FOV!)
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: https://imgur.com/iIFEPcC
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;
}
}
}
@zacharygears Please share your current relevant code for the camera movement. Edit your question and add it, but use proper code formatting so it will show up right.
I edited my question to paste in my scripts and hit the confirm button, but it doesn't seem like my scripts are showing up on this page.
EDIT: never$$anonymous$$d. It's showing up now.
If I understand you correctly the lerp function does work but it's not smooth enough. Then just make it smooth:
curZoom = (targetZoom - curZoom) * movePerc;
$$anonymous$$athf.Lerp($$anonymous$$Zoom, maxZoom, curZoom);
Answer by metalted · Mar 14, 2020 at 09:52 PM
You can put this script on your camera. The camera has to be a child of another transform and have position and rotation at 0. You can then use the parent for rotation.
using UnityEngine;
public class CameraMove : MonoBehaviour
{
public float zoomSpeed = 10f;
public float minZ = -10f;
public float maxZ = -3;
public float smoothTime = 0.3f;
private float movePosition;
private float smoothVelocity = 0;
private float smoothMove;
public void Start()
{
movePosition = transform.localPosition.z;
smoothMove = movePosition;
}
public void Update()
{
float wheel = Input.GetAxis("Mouse ScrollWheel");
if (wheel != 0)
{
movePosition += wheel * zoomSpeed;
movePosition = Mathf.Clamp(movePosition, minZ, maxZ);
}
if(Mathf.Abs(movePosition - smoothMove) > 0.001f)
{
smoothMove = Mathf.SmoothDamp(smoothMove, movePosition, ref smoothVelocity, smoothTime);
Vector3 targetPosition = new Vector3(0, 0, smoothMove);
transform.localPosition = targetPosition;
}
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220612224942im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Limit camera pan not working 0 Answers
How to move a camera only using the arrow keys? 7 Answers
How do I tell a button to move my camera!? 1 Answer
Move camera when reach edge of screen in C# 0 Answers
GUI.Box and Camera Movement 1 Answer