- Home /
Camera smooth Zoom in/out (without FieldOfView)
Hello,
I'm trying to create a smooth camera zoom in/out by moving the camera on the Z axis (and not changing the FieldOfView). I managed to do the zoom out part smoothly, although the zoom in part has the same code that should work the same, but unfortunately it isn't working smoothly. Here's the zoom code:
private void Zoom()
{
float oldDist = m_OriginalDist;
m_OriginalDist -= Input.GetAxis ("Mouse ScrollWheel") * m_ZoomSensitivity;
m_OriginalDist = Mathf.Clamp (m_OriginalDist, m_MinZoom, m_MaxZoom);
float smoothZooming = Mathf.Lerp (m_Cam.position.z, m_OriginalDist, Time.deltaTime * 50f);
m_Cam.position = new Vector3 (m_Cam.position.x, m_Cam.transform.position.y, smoothZooming);
if (m_OriginalDist != oldDist) {
float newPosition = m_Pivot.position.y - Input.GetAxis ("Mouse ScrollWheel") * m_PivotSensitivity;
newPosition = Mathf.Clamp (newPosition, 1f, 10f);
smoothZooming = Mathf.Lerp (m_Pivot.position.y, newPosition, Time.deltaTime * 5f);
m_Pivot.position = new Vector3 (m_Pivot.position.x, smoothZooming, m_Pivot.position.z);
}
}
I tried multiple methods found on the internet, and searched for solutions but most of them use the FieldOfView.
NOTE: I'm using the the FreeLookCameraRig that comes with unity's standard assets, and i'm using this function in the ProtectCameraFromWallClip script. Also I'm increasing the pivot "smoothly" when zooming out and vis versa.
Any help is appreciated
Without FieldOfView you can't zoom. I think your code it will changing its position not for zoom.
yea well what my code does is just take the camera away from the player or gets closer to him (talking about 3rd person camera). What i'm trying to do is a camera like TERA, the 1st $$anonymous$$ute of this video shows exactly what i'm trying to do in my camera: https://www.youtube.com/watch?v=E9IfuE7wXb8
The OP is looking for a 'dolly' effect, not a FOV zoom. Converting to comment.
http://answers.unity3d.com/questions/11076/camera-controls-zoom-vs-dolly.html
I think the problem is using positions and lerping between them (having trouble understanding your code).
Another method would be to : get the relative direction of the camera to the object; normalize relative direction; multiply normalized relative direction by the desired distance; add to the position of the object.
Check this post : http://forum.unity3d.com/threads/orbit-pan-zoom-in-one-script.11091/#post-352377 ; derived from this thread : http://forum.unity3d.com/threads/wow-camera-movement.16949/
@alucardj yes that's exactly what i'm looking for! The "dolly effect". I have found out my problem though i was unable to fix it.
This script "ProtectCameraFromWallClip" i'm using is from the "FreeLookCameraRig" that comes with unity's standard assets, so you can download it and set it up and add my Zoom function which I have modified below:
private void Zoom()
{
float oldDist = m_OriginalDist;
m_OriginalDist -= Input.GetAxis ("$$anonymous$$ouse ScrollWheel") * m_ZoomSensitivity;
m_OriginalDist = $$anonymous$$athf.Clamp (m_OriginalDist, m_$$anonymous$$inZoom, m_$$anonymous$$axZoom);
}
$$anonymous$$y problem turned out in the last 3 lines in the "LateUpdate" function:
m_CurrentDist = $$anonymous$$athf.SmoothDamp(m_CurrentDist, targetDist, ref m_$$anonymous$$oveVelocity, m_CurrentDist > targetDist ? clip$$anonymous$$oveTime : returnTime);
m_CurrentDist = $$anonymous$$athf.Clamp(m_CurrentDist, closestDistance, m_OriginalDist);
m_Cam.localPosition = -Vector3.forward*m_CurrentDist;
They have been overriding my previous "Zoom" function.
Please help me by setting up the "FreeLookCameraRig" and fixing my "Zoom" function.
Help is GREATLY appreciated!
Answer by lello200 · Jul 03, 2016 at 12:32 PM
@alucardj exactly what i'm looking for is a "dolly effect" and not a FOV zoom. I found out my problem though I wasn't able to fix it. Here's the full code of the script that zooms and protects the camera from wall:
using System; using System.Collections; using UnityEngine;
public class ProtectCameraFromWallClip : MonoBehaviour
{
public float clipMoveTime = 0.05f; // time taken to move when avoiding cliping (low value = fast, which it should be)
public float returnTime = 0.4f; // time taken to move back towards desired position, when not clipping (typically should be a higher value than clipMoveTime)
public float sphereCastRadius = 0.1f; // the radius of the sphere used to test for object between camera and target
public bool visualiseInEditor; // toggle for visualising the algorithm through lines for the raycast in the editor
public float closestDistance = 0.5f; // the closest distance the camera can be from the target
public bool protecting { get; private set; } // used for determining if there is an object between the target and the camera
public string dontClipTag = "Player"; // don't clip against objects with this tag (useful for not clipping against the targeted object)
public float m_MinZoom = 4f;
public float m_MaxZoom = 20f;
public float m_ZoomSensitivity = 5f;
public float m_PivotSensitivity = 15f;
private Transform m_Cam; // the transform of the camera
private Transform m_Pivot; // the point at which the camera pivots around
private float m_OriginalDist; // the original distance to the camera before any modification are made
private float m_MoveVelocity; // the velocity at which the camera moved
private float m_CurrentDist; // the current distance from the camera to the target
private Ray m_Ray; // the ray used in the lateupdate for casting between the camera and the target
private RaycastHit[] m_Hits; // the hits between the camera and the target
private RayHitComparer m_RayHitComparer; // variable to compare raycast hit distances
private void Start()
{
// find the camera in the object hierarchy
m_Cam = GetComponentInChildren<Camera>().transform;
m_Pivot = m_Cam.parent;
m_OriginalDist = m_Cam.localPosition.magnitude;
m_CurrentDist = m_OriginalDist;
// create a new RayHitComparer
m_RayHitComparer = new RayHitComparer();
}
private void LateUpdate()
{
Zoom ();
// initially set the target distance
float targetDist = m_OriginalDist;
m_Ray.origin = m_Pivot.position + m_Pivot.forward*sphereCastRadius;
m_Ray.direction = -m_Pivot.forward;
// initial check to see if start of spherecast intersects anything
var cols = Physics.OverlapSphere(m_Ray.origin, sphereCastRadius);
bool initialIntersect = false;
bool hitSomething = false;
// loop through all the collisions to check if something we care about
for (int i = 0; i < cols.Length; i++)
{
if ((!cols[i].isTrigger) &&
!(cols[i].attachedRigidbody != null && cols[i].attachedRigidbody.CompareTag(dontClipTag)))
{
initialIntersect = true;
break;
}
}
// if there is a collision
if (initialIntersect)
{
m_Ray.origin += m_Pivot.forward*sphereCastRadius;
// do a raycast and gather all the intersections
m_Hits = Physics.RaycastAll(m_Ray, m_OriginalDist - sphereCastRadius);
}
else
{
// if there was no collision do a sphere cast to see if there were any other collisions
m_Hits = Physics.SphereCastAll(m_Ray, sphereCastRadius, m_OriginalDist + sphereCastRadius);
}
// sort the collisions by distance
Array.Sort(m_Hits, m_RayHitComparer);
// set the variable used for storing the closest to be as far as possible
float nearest = Mathf.Infinity;
// loop through all the collisions
for (int i = 0; i < m_Hits.Length; i++)
{
// only deal with the collision if it was closer than the previous one, not a trigger, and not attached to a rigidbody tagged with the dontClipTag
if (m_Hits[i].distance < nearest && (!m_Hits[i].collider.isTrigger) &&
!(m_Hits[i].collider.attachedRigidbody != null &&
m_Hits[i].collider.attachedRigidbody.CompareTag(dontClipTag)))
{
// change the nearest collision to latest
nearest = m_Hits[i].distance;
targetDist = -m_Pivot.InverseTransformPoint(m_Hits[i].point).z;
hitSomething = true;
}
}
// visualise the cam clip effect in the editor
if (hitSomething)
{
Debug.DrawRay(m_Ray.origin, -m_Pivot.forward*(targetDist + sphereCastRadius), Color.red);
}
// hit something so move the camera to a better position
protecting = hitSomething;
m_CurrentDist = Mathf.SmoothDamp(m_CurrentDist, targetDist, ref m_MoveVelocity, m_CurrentDist > targetDist ? clipMoveTime : returnTime);
m_CurrentDist = Mathf.Clamp(m_CurrentDist, closestDistance, m_OriginalDist);
m_Cam.localPosition = -Vector3.forward*m_CurrentDist;
}
private void Zoom()
{
float oldDist = m_OriginalDist;
m_OriginalDist -= Input.GetAxis ("Mouse ScrollWheel") * m_ZoomSensitivity;
m_OriginalDist = Mathf.Clamp (m_OriginalDist, m_MinZoom, m_MaxZoom);
}
// comparer for check distances in ray cast hits
public class RayHitComparer : IComparer
{
public int Compare(object x, object y)
{
return ((RaycastHit) x).distance.CompareTo(((RaycastHit) y).distance);
}
}
}
The problem is in these 3 lines that are at the end of the "LateUpdate" function:
m_CurrentDist = Mathf.SmoothDamp(m_CurrentDist, targetDist, ref m_MoveVelocity, m_CurrentDist > targetDist ? clipMoveTime : returnTime);
m_CurrentDist = Mathf.Clamp(m_CurrentDist, closestDistance, m_OriginalDist);
m_Cam.localPosition = -Vector3.forward*m_CurrentDist;
If you want to set up the camera, just download the standard assets from the asset store, and use the "FreeLookCameraRig", and add my "Zoom" function to the "ProtectCameraFromWallClip".
P.S.: I have changed the "Zoom" function from my first post.
Any help is GREATLY appreciated!
Your answer
Follow this Question
Related Questions
Camera zoom smoothing 1 Answer
Camera Follow sphere with ridgidbody? 4 Answers
Zoom camera based on position between player an object 2 Answers
How can I zoom out a camera locked on the player? 0 Answers
Camera Smooth Follow 2 Answers