0

I have a dynamic FOV and crouching script for my player which both use the Lerp function for smooth camera movement, but it only works for the increase in FOV and decrease in height. When the FOV and height return to normal, it just snaps back instantly rather than giving the smooth movement expected.

Crouching:

if (Input.GetKey(KeyCode.LeftControl))
        {
            characterController.height = Mathf.Lerp(characterController.height, 0.5f, 10f * Time.deltaTime);
            canRun = false;
            canJump = false;
            walkingSpeed = 2f;
        }

        else
        {
            characterController.height = Mathf.Lerp(characterController.height, 2.0f, 10f * Time.deltaTime);
            canRun = true;
            canJump = true;
            walkingSpeed = 4f;
        }

FOV:

if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D))
            {
                Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView, 65f, 10f * Time.deltaTime);
            }

            else
            {
                Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView, 60f, 10f * Time.deltaTime);
            }

I've looked online but no one seems to be having this issue and the code looks like it should work. (I am new to this so it's probably something really obvious)

derHugo
  • 83,094
  • 9
  • 75
  • 115
lunixd
  • 13
  • 4
  • Look at the documentation of lerp. Using a constant value is probably not what you want. Usually you increment `t` from 0 to 1 so that the value transitions from A to B. – hijinxbassist Jul 24 '23 at 19:42
  • @hijinxbassist using a constant value here is fine as it's not interpolating from 0.5 to 2.0 for example, it's going from the *current* height to 2.0 – nullFoo Jul 24 '23 at 22:39
  • @nullFoo, You're right that it's not *wrong* per se, but it really isn't a great practice, especially for things like camera manipulation. It is totally framerate dependant and large or tiny values will cause some very strange effects. – Jay Jul 25 '23 at 09:52

2 Answers2

0

If you want to lerp between two states, you would be best to store the lerp value as it's state is what determines the camera's position.

if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D))
{
    lerpValue = Mathf.Clamp01(lerpValue + (speed * Time.deltaTime))
}
else
{
    lerpValue = Mathf.Clamp01(lerpValue - (speed * Time.deltaTime))
}

Then use this value to perform your easing. I'm using smoothstep here instead of using a variable as a lerp minimum.

Camera.main.fieldOfView = Mathf.SmoothStep(60, 65, lerpValue);

Using a variable as the minimum like x = Lerp(x, 10, t); can really lead to some weird behaviour... imagine you have a framerate dip and delta time is ever 1.2s... what would happen? I very much don't recommend doing it this way and using tweeining function instead. Check out https://easings.net

This should ease your camera's fov without snapping. The same can be used for crouching.

Jay
  • 2,553
  • 3
  • 17
  • 37
  • 1
    if there is a frame rate drop to 1.2 seconds you would probably be fine with it jumping to the target value though ;) – derHugo Jul 25 '23 at 09:55
  • Okay sure, bad example lol. I think it is bad practice though - a spike like that is the *only* time the end value would actually be reached, and the effect would look different depending on framerate right? – Jay Jul 25 '23 at 11:00
  • @jay - yes, it will be an approximation, like 14,9999999999987 but it's still useful. You have a fast but decelerating movement that is pretty much framerate independent. While smoothDamp or a local variable `float t` for Lerp would help, it's not always practical when the goal changes a lot (like a follower system, or if you quickly toggle sprint/walk or duck/walk). – KYL3R Jul 25 '23 at 13:35
  • @Jay, btw. you clamp the `lerpValue` to 01. Why? There is [Mathf.Clamp](https://docs.unity3d.com/ScriptReference/Mathf.Lerp.html) which already does this: `The parameter t is clamped to the range [0, 1].` and there is also [Mathf.LerpUnclamped](https://docs.unity3d.com/ScriptReference/Mathf.LerpUnclamped.html) if you ever need it. – KYL3R Jul 25 '23 at 13:37
  • @KYL3R if you don't clamp the t value then it will continually increase. When you want it to decrease again then it would have to travel this distance down again before it had any effect on the lerp. If you want to use a tweening funciton then tween it, why use the unreliable hack with lerp. It's also very much framerate dependant, try it out yourself while limiting the frame-rate... – Jay Jul 25 '23 at 13:42
  • @KYL3R If you really want to do it this way then you can make it framerate independant, you just need to do the strange looking `x = Lerp(x, 10, (1- Mathf.Pow(speed, Time.deltaTime)))`, – Jay Jul 25 '23 at 13:53
0

Code looks fine, also works fine. Tested the FOV here:

https://i.imgur.com/Wo6a0hP.mp4

You probably have another script manipulating the FOV, causing it to snap back immediately.

KYL3R
  • 3,877
  • 1
  • 12
  • 26