- Home /
Camera zoom AND smooth transition?
So here's what I'm trying to do:
I am working on a camera that can switch from Orthographic to Perspective upon the push of a button.
I have one script that allows the camera to transition between the two perspectives smoothly.
I have another script that can change the zoom and size of the two camera styles by using the scrollwheel.
I cannot for the life of me get these two separate scripts to have functionality at the same time. Something always conflicts with something else and I can only get one or the other to work. Where am I going wrong?
Any help would be greatly appreciated, I have been trying to solve this for over a week.
Scrollwheel script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControllerWorking : MonoBehaviour
{
public Transform target;
public Vector3 offset;
public float zoomSpeed = 4f; //Meet float zoomSpeed. This float lets you zoom in and out!
public float zoomSpeedOrtho = 1f;
public float minZoom = 5f; //Meet float minZoom. This is the smallest you can zoom. Set the number to what feels right
public float maxZoom = 15f; //Meet float maxZoom. This is the FURTHEST you can zoom. Same advice as before!
public float minZoomOrtho = 0.7f;
public float maxZoomOrtho = 2f;
public float CurrentCameraStyle;
public float pitch = 2f;
private float currentZoom = 10f;
private float currentZoomOrtho = 1f;
void Start()
{
CurrentCameraStyle = -1;
}
void Update ()
{
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed; //Okay, now currentZoom's value is going to be... hold on, let me wait for the scrollwheel... okay, that number multiplied by the number we have in zoomSpeed (which right now is 4 unless we edit it), and THEN invert that number to a negative integer.
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom); //Whatever number we get, it HAS to be between the numbers given in minZoom and maxZoom. That's why it's called "clamping" (I think)
Camera.main.orthographicSize -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeedOrtho;
Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize, minZoomOrtho, maxZoomOrtho);
if (Input.GetKeyDown(KeyCode.Space))
{
CurrentCameraStyle = -CurrentCameraStyle;
}
if (CurrentCameraStyle == -1)
{
Camera.main.orthographic = true; //Change the camera's style to orthographic
transform.position = target.position + new Vector3(0, 5, 0); //Change the camera's position to whatever the target's current position is and add 5 on the Y-axis so you're not directly on top of it
transform.eulerAngles = new Vector3(90, 0, 0); //Change the camera's angle to PRECISELY 90 degrees downwards on the X-axis, leave the Y-axis and Z-axis at 0
}
else
{
Camera.main.orthographic = false; //Change the camera's style to perspective
transform.position = target.position - offset * currentZoom; //
transform.LookAt(target.position + Vector3.up * pitch); //
}
}
/*
void LateUpdate () //LateUpdate is basically exactly like Update except it happens after. I guess. But why such an arbitrary name? Why can't I make as many updates as I want? Why only Update and then LateUpdate? How does this work?
{
}
*/
}
Smooth transition script:
using UnityEngine;
using System.Collections;
//https://forum.unity.com/threads/smooth-transition-between-perspective-and-orthographic-modes.32765/
[RequireComponent (typeof(MatrixBlender))]
public class PerspectiveSwitcherWorking : MonoBehaviour
{
public Transform target;
private Matrix4x4 ortho,
perspective;
public float fov = 60f,
near = .3f,
far = 1000f,
orthographicSize = 2f;
private float aspect;
private MatrixBlender blender;
private bool orthoOn;
void Start()
{
aspect = (float) Screen.width / (float) Screen.height;
ortho = Matrix4x4.Ortho(-orthographicSize * aspect, orthographicSize * aspect, -orthographicSize, orthographicSize, near, far);
perspective = Matrix4x4.Perspective(fov, aspect, near, far);
GetComponent<Camera>().projectionMatrix = ortho;
orthoOn = true;
blender = (MatrixBlender) GetComponent(typeof(MatrixBlender));
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
orthoOn = !orthoOn;
if (orthoOn)
blender.BlendToMatrix(ortho, 0.25f);
else
blender.BlendToMatrix(perspective, 0.25f);
}
}
}
This script requires another one called BlendMatrix, not sure if this will help but here it is:
using UnityEngine; //Oooookay full disclosure, I have NO IDEA what most of this means. I got this straight from Unity user tomvds.
using System.Collections; //Source: https://forum.unity.com/threads/smooth-transition-between-perspective-and-orthographic-modes.32765/
[RequireComponent (typeof(Camera))] //This line basically means that it requires a Camera component otherwise it won't do anything
public class MatrixBlender : MonoBehaviour
{
public static Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float time) //Meet Matrix4x4 named MatrixLerp.
{
Matrix4x4 ret = new Matrix4x4();
for (int i = 0; i < 16; i++) //Now for as long as- oh by the way this is integer named i, say hello- as long as i is less than 16, add 1 digit to i. Keep doing this until i equals 16.
ret[i] = Mathf.Lerp(from[i], to[i], time); //
return ret;
}
private IEnumerator LerpFromTo(Matrix4x4 src, Matrix4x4 dest, float duration) //Meet IEnumerator named LerpFromTo.
{
float startTime = Time.time;
while (Time.time - startTime < duration)
{
GetComponent<Camera>().projectionMatrix = MatrixLerp(src, dest, (Time.time - startTime) / duration);
yield return 1;
}
GetComponent<Camera>().projectionMatrix = dest;
}
public Coroutine BlendToMatrix(Matrix4x4 targetMatrix, float duration) //A coroutine makes it so that it waits until the given YieldInstruction is done before it does its code. In this case, BlendToMatrix.
{
StopAllCoroutines(); //Stop every coroutine
return StartCoroutine(LerpFromTo(GetComponent<Camera>().projectionMatrix, targetMatrix, duration)); //Now that every other coroutine has stopped, begin the coroutine named LerpFromTo
}
}