Skip to content

Instantly share code, notes, and snippets.

@CriticalAngle
Last active August 31, 2024 03:30
Show Gist options
  • Save CriticalAngle/e93fa92c294c9ebce035374f4ea930b7 to your computer and use it in GitHub Desktop.
Save CriticalAngle/e93fa92c294c9ebce035374f4ea930b7 to your computer and use it in GitHub Desktop.
Critical Lerp

In Unity, instead of having to create a new IEnumerator for every time that you would like to linearly interpolate a value, you can use this function to handle the skeleton code.

Example

public class CameraManager : MonoBehaviour
{
    [SerializeField] private Camera camera;
    [SerializeField] private Transform point;

    [Space] [SerializeField] private float zoomTime = 1.0f;
    
    public void ZoomToPoint(Transform point)
    {
        this.Lerp(
            this.camera.transform.position,
            point.position,
            this.zoomTime,
            Vector3.Lerp,
            position => this.camera.transform.position = position,
            Easings.InOutSine);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            ZoomToPoint(this.point);
    }
}
using System;
using System.Collections;
using JetBrains.Annotations;
using UnityEngine;
namespace CriticalAngleStudios.Lerp
{
public static class CriticalLerp
{
public static void Lerp<T>(
this MonoBehaviour self,
T initial,
T final,
float time,
Func<T, T, float, T> lerp,
Action<T> perform,
[CanBeNull] Func<float, float> easing = null
)
{
self.StartCoroutine(Lerp_Internal(initial, final, time, lerp, perform, easing ?? Easings.InOutSine));
}
private static IEnumerator Lerp_Internal<T>(
T initial,
T final,
float time,
Func<T, T, float, T> lerp,
Action<T> perform,
Func<float, float> easing
)
{
var t = 0.0f;
while (t < time)
{
perform.Invoke(lerp.Invoke(initial, final, easing.Invoke(t / time)));
t += Time.deltaTime;
yield return null;
}
perform.Invoke(final);
}
}
}
using UnityEngine;
// ReSharper disable MemberCanBePrivate.Global
namespace CriticalAngleStudios.Lerp
{
public static class Easings
{
public static float Linear(float t) => t;
public static float InQuad(float t) => t * t;
public static float OutQuad(float t) => 1.0f - InQuad(1.0f - t);
public static float InOutQuad(float t)
{
if (t < 0.5f) return InQuad(t * 2.0f) / 2.0f;
return 1.0f - InQuad((1.0f - t) * 2.0f) / 2.0f;
}
public static float InCubic(float t) => t * t * t;
public static float OutCubic(float t) => 1.0f - InCubic(1.0f - t);
public static float InOutCubic(float t)
{
if (t < 0.5f) return InCubic(t * 2.0f) / 2.0f;
return 1.0f - InCubic((1.0f - t) * 2.0f) / 2.0f;
}
public static float InQuart(float t) => t * t * t * t;
public static float OutQuart(float t) => 1.0f - InQuart(1.0f - t);
public static float InOutQuart(float t)
{
if (t < 0.5f) return InQuart(t * 2.0f) / 2.0f;
return 1.0f - InQuart((1.0f - t) * 2.0f) / 2.0f;
}
public static float InQuint(float t) => t * t * t * t * t;
public static float OutQuint(float t) => 1.0f - InQuint(1.0f - t);
public static float InOutQuint(float t)
{
if (t < 0.5f) return InQuint(t * 2.0f) / 2.0f;
return 1.0f - InQuint((1.0f - t) * 2.0f) / 2.0f;
}
public static float InSine(float t) => -Mathf.Cos(t * Mathf.PI / 2.0f);
public static float OutSine(float t) => Mathf.Sin(t * Mathf.PI / 2.0f);
public static float InOutSine(float t) => (Mathf.Cos(t * Mathf.PI) - 1.0f) / -2.0f;
public static float InExpo(float t) => Mathf.Pow(2.0f, 10.0f * (t - 1.0f));
public static float OutExpo(float t) => 1.0f - InExpo(1.0f - t);
public static float InOutExpo(float t)
{
if (t < 0.5f) return InExpo(t * 2.0f) / 2.0f;
return 1.0f - InExpo((1.0f - t) * 2.0f) / 2.0f;
}
public static float InCirc(float t) => -(Mathf.Sqrt(1.0f - t * t) - 1.0f);
public static float OutCirc(float t) => 1.0f - InCirc(1.0f - t);
public static float InOutCirc(float t)
{
if (t < 0.5f) return InCirc(t * 2.0f) / 2.0f;
return 1.0f - InCirc((1.0f - t) * 2.0f) / 2.0f;
}
public static float InElastic(float t) => 1.0f - OutElastic(1.0f - t);
public static float OutElastic(float t)
{
const float p = 0.3f;
return Mathf.Pow(2.0f, -10.0f * t) * Mathf.Sin((t - p / 4.0f) * (2.0f * Mathf.PI) / p) + 1.0f;
}
public static float InOutElastic(float t)
{
if (t < 0.5f) return InElastic(t * 2.0f) / 2.0f;
return 1.0f - InElastic((1.0f - t) * 2.0f) / 2.0f;
}
public static float InBack(float t)
{
const float s = 1.70158f;
return t * t * ((s + 1.0f) * t - s);
}
public static float OutBack(float t) => 1.0f - InBack(1.0f - t);
public static float InOutBack(float t)
{
if (t < 0.5f) return InBack(t * 2.0f) / 2.0f;
return 1.0f - InBack((1.0f - t) * 2.0f) / 2.0f;
}
public static float InBounce(float t) => 1.0f - OutBounce(1.0f - t);
public static float OutBounce(float t)
{
const float div = 2.75f;
const float mult = 7.5625f;
switch (t)
{
case < 1.0f / div:
return mult * t * t;
case < 2.0f / div:
t -= 1.5f / div;
return mult * t * t + 0.75f;
case < 2.5f / div:
t -= 2.25f / div;
return mult * t * t + 0.9375f;
}
t -= 2.625f / div;
return mult * t * t + 0.984375f;
}
public static float InOutBounce(float t)
{
if (t < 0.5f) return InBounce(t * 2.0f) / 2.0f;
return 1.0f - InBounce((1.0f - t) * 2.0f) / 2.0f;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment