- Home /
Using While Function For Field Of View - Camera
Hello,
I'm adding a zoom function to my rifle, which is basically just lowering the field of view on the main camera. So, when zoom is true:
Camera.main.fieldOfView = 40;
else
Camera.main.fieldOfView = 60;
But I want to make it animated, and I'm guessing I can achieve that by using a 'Time.deltaTime' in a while function:
function Zoom(){
if(zoomOn == false){
zoomOn = true;
while(Camera.main.fieldOfView > 40){
Camera.main.fieldOfView -= Time.deltaTime ;
}
}
But all this does is jump straight to 40, it doesn't slowly decrease from 60, to 40 ... Any ideas why?
Thanks
Answer by GuyTidhar · Aug 04, 2011 at 02:14 PM
Use a coroutine so you only zoom when you need to and avoid update when possible (which in this case is possible):
public var zoomDuration : float = 0.5;
private var zooming : boolean = false;
function Zoom()
{
if ( !zooming )
StartCoroutine("ZoomIn");
}
private function ZoomIn()
{
var deltaT : float = 0;
zooming = true;
while ( deltaT < zoomDuration )
{
deltaT += Time.deltaTime;
yield;
Camera.main.fieldOfView = Mathf.Lerp(60, 40, deltaT / zoomDuration);
}
}
Answer by benni05 · Aug 04, 2011 at 02:00 PM
Because your while-loop is executed during one single frame.
if the Zoom function is called from an Update function you can just replace the "while" with an "if" like this:
if(zoomOn == false){
zoomOn = true;
} else {
if (Camera.main.fieldOfView > 40){
Camera.main.fieldOfView -= Time.deltaTime ;
}
}
The built-in Update function already works like a "while" so to speak.
Ben
Okay - but its not called from the update, so what would I do then?
Then the co-routine answer below is the one I would suggest as well.
Answer by TheDarkVoid · Aug 04, 2011 at 02:44 PM
This is what i used to get it done in my game:
var wasDown = false;
void Update()
{
if(Input.GetMouseButton(1))
{
if(Camera.main.fieldOfView > 15)
Camera.main.fieldOfView -= 5;
if(Camera.main.fieldOfView < 15)
Camera.main.fieldOfView = 15;
}
if(Input.GetMouseButtonUp(1))
{
wasDown = true;
}
if(wasDown)
{
if(Camera.main.fieldOfView <= 50)
Camera.main.fieldOfView += 5;
if(Camera.main.fieldOfView > 50)
Camera.main.fieldOfView = 50;
if(Camera.main.fieldOfView == 50)
{
wasDown = false;
}
}
}
This is an okay methord, but if your game is on a slower computer, then the zoom would occur slower as there are less frames per second.
yea, i will improve upon it but the same layout can be used
Answer by getluky · Aug 04, 2011 at 07:28 PM
I don't like using coroutines for this type of thing, because a zoom-tap will look all screwed up if you end up with a zoom-in and a zoom-out fighting each other. I prefer setting an active target and using the Update method to lerp towards it with a threshold at which it snaps into place. Apologies for any errors in the below c# snippet:
float zoomTarget = 60.0f;
public float zoomSnapThreshold = 0.1f;
public float zoomSpeed = 1.0f;
public void SetZoomTarget(float to) {
zoomTarget = to;
}
void Update() {
float curFOV = Camera.main.fieldOfView;
if (Mathf.Abs(zoomTarget - curFOV) > zoomSnapThreshold) {
Camera.main.fieldOfView = Mathf.Lerp(curFOV, zoomTarget, Time.deltaTime * zoomSpeed);
} else {
Camera.main.fieldOfView = zoomTarget;
}
}
You could attach this to a C# script and it would move your camera FOV to the target whenever you call SetZoomTarget with a new value. Then you tweak the zoomSpeed value to get a faster zoom, and if it looks jerky at the very end, lower the zoomSnapThreshold keeping it above 0. You could also get fancy if you want to use a different interpolation method, but this should do the trick.
And to answer your original question, a basic rule of thumb might help that Time.deltaTime is only useful inside Update or while loops that yield for a frame (i.e. in coroutines). The way you have it written, it will wind all the way down in the same frame because it never yields for the next frame.
You can still use coroutines and avoid any such screw ups and not use update when you don't have to. Just stop and start the zoom in and zoom out before calling the opposite and make sure you keep setting the same value.
$$anonymous$$any ways to skin a cat. There will be slight differences in operation between these two methods, as any Lerp over Time.deltaTime influenced values will appear to ease out without an exact duration, and guyt's will move linearly over an exact duration. From a performance point of view, I wouldn't really say that these two choices are all that different. I'd think that caching the Camera.main reference would have more impact than the overhead of a couple of arithmetic operations in the Update loop for a single GameObject.
Your answer

Follow this Question
Related Questions
Global 'orbital' map of terrain 0 Answers
Change field of view over time 1 Answer
Script to constantly change FOV? 1 Answer
Sensitivity Help? || Scope Zoom 1 Answer
How to fix(reduce) skewing of objects when changing fieldOfView 0 Answers