1
\$\begingroup\$

I rotate my camera using a framerate-independent exponential ease-out blend like so:

    _x += Input.GetAxis("Mouse X") * xSpeed;
    float target = 0f; //I want to blend towards 0
    float sharpness = 0.05f; //the smaller this value, the longer it takes to settle down to the target value
    float referenceFramerate = 90f;//the approximate framerate on my developer machine
    float blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
    _x = Mathf.Lerp(_x, target, blend);

This works fine.

Now my camera should be clipped at a certain rotation yaw.

The new camera rotation yaw is calculated like this:

    _CurrentYaw += _x * Mathf.Abs(_CameraDefaultPos.z);
    if (_CurrentYaw > 160f)
    {
       _CurrentYaw = 160f;
    }
    else if (_CurrentYaw < -120f)
    {
       _CurrentYaw = -120f;
    }

This clipping part of my code makes the camera stop abruptly at the maximum.

How could the above Mathf.Lerp function be adopted to make it so that the _x value would be damped more quickly when going towards the rotation limit?

\$\endgroup\$
7
  • \$\begingroup\$ It's not immediately clear what your _x variable represents. It looked like it was a rotation angle, but in your latest edits we see it added to a _CurrentYaw value - is that happening every frame, making _x a rate of change over time? Should that not be delta-time-corrected too then? \$\endgroup\$
    – DMGregory
    Commented Feb 13, 2019 at 18:24
  • \$\begingroup\$ @DMGregory All this is executed each frame. "_x" is the "Mouse X" value that I get from the user over time. I use this (after blending) as the Yaw of my camera. Since I already blend _x, there's no need to delta-time-correct the Yaw of the camera, I believe. I hope I could make this understandable? You see that "_x" and camera Yaw are stored independently. That is because I want to accumulate the user's input and give it away to the camera rotation over time (that's how I would describe it in words). This way, the camera rotates nicely between left and right when direction changes. \$\endgroup\$
    – tmighty
    Commented Feb 13, 2019 at 18:40
  • \$\begingroup\$ Double your framerate and _CurrentYaw will change twice as fast, since you're adding _x to it twice as often. \$\endgroup\$
    – DMGregory
    Commented Feb 13, 2019 at 18:51
  • \$\begingroup\$ @DMGregory But I thought the blend function - which I use on "_x" before setting the Yaw of the camera - would make it frame-rate independent. Is that not true? \$\endgroup\$
    – tmighty
    Commented Feb 13, 2019 at 19:06
  • \$\begingroup\$ Blend functions don't leave a magic coating on the number that carries over to the next operation. Let's say your blended variable comes out to be 0.5. If you add that value 30 times per second, after 1 second you've gone up by 15. If you add that value 60 times per second, after 1 second you've gone up by 30. The fact that 0.5 was the output of a framerate-independent blending just says that its rate of change is consistent. The rate of change of stuff you add it to depends on how you add it. \$\endgroup\$
    – DMGregory
    Commented Feb 13, 2019 at 19:26

1 Answer 1

1
\$\begingroup\$

Here's one way you can tackle it: computing how far you are from the center of the allowed range, and applying a braking multiplier the closer you are to the edge.

public class LimitedCameraYaw : MonoBehaviour
{
    const float referenceFramerate = 30.0f;

    public float yawCenter = 20;
    public float yawRange = 140;

    public float yawInputFalloff = 0.01f;
    public float yawSpeed = 60.0f;

    float _currentYaw;
    float _yawRate;

    void Update() {
        // Fade old input before capturing new, so we don't dull the freshest data.
        float blend = Mathf.Pow(1.0f - yawInputFalloff, referenceFramerate * Time.deltaTime);
        // A Lerp toward zero is just the same as a multiplication by the complement of the blend factor.    
        _yawRate *= blend;

        // Accelerate by mouse movement over the past frame.
        // (May need adjustment for display resolution).
        _yawRate += Input.GetAxis("Mouse X");

        float yawDelta = yawSpeed * _yawRate * Time.deltaTime;

        float offCenter = _currentYaw - yawCenter;

        // If we're moving away from the center, slow down as we approach the edge.
        if (yawDelta * offCenter > 0) {
            float extremity = offCenter / yawRange;
            yawDelta *= 1.0f - extremity * extremity;
        }

        // Ensure we never overshoot the allowed range.
        _currentYaw = Mathf.Clamp(_currentYaw + yawDelta,
                                  yawCenter - yawRange,
                                  yawCenter + yawRange);

        transform.eulerAngles = Vector3.up * _currentYaw;
    }
}
\$\endgroup\$
7
  • \$\begingroup\$ Could you please test the following? Set Yaw Input Falloff to 0.95f and observe. There is almost no drift happening if there is no more input. Now set Yaw Input Falloff to 1f. You'll probally notice that now there's a huuuuge drift happening. Can you reproduce this? \$\endgroup\$
    – tmighty
    Commented Feb 14, 2019 at 15:25
  • \$\begingroup\$ Here's a video of my results: youtu.be/_FxjEXx4B-Y \$\endgroup\$
    – tmighty
    Commented Feb 14, 2019 at 15:29
  • 1
    \$\begingroup\$ The meaningful range for a falloff multiplier is 0 < multiplier < 1. It's not expected to give a meaningful value at or above 1.0. I did forget to remove the "1 - ..." when simplifying the Lerp to a multiply, so try it without that. You'll likely want a low falloff value, close to zero. \$\endgroup\$
    – DMGregory
    Commented Feb 14, 2019 at 15:53
  • \$\begingroup\$ Yes, that fixed it. Your improved version of my script is really a beautiful kind of art. :-) \$\endgroup\$
    – tmighty
    Commented Feb 14, 2019 at 16:07
  • \$\begingroup\$ Would you mind including that "adjustment for display resolution"? A generic idea would be great (as this is something that I'm currently fighting with). I feel that there's a lot to learn from you. \$\endgroup\$
    – tmighty
    Commented Feb 14, 2019 at 16:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .