- alexlpc2015
[Unity Coding Designs] #04 - Tweening
Hi and welcome to my Unity Coding Designs Series!
This is a comprehensive series about various coding designs in unity. Some of the scripts are included in my unity utility plugin SKCell. I hope you will find this helpful!
Coding Designs #04 - Tweening
In the last tutorial, we set up the animation curve sampler. This time we will write a function that uses the animation curves to create an animation effect. After this tutorial, we can achieve effects like this using only one line of code!

Inside the static utility class, write a new function. It will create a dynamically varying float value over a certain span of time. We can then grab the float and use it for our effects.
/// <summary>
/// Starts a continuous procedure where a variable changes from 0 to 1 over time. Tweening.
/// </summary>
/// <param name="curve">Curve of the procedure.</param>
/// <param name="variable">Procedure variable.</param>
/// <param name="action">Action called per frame.</param>
/// <param name="onFinish">Action called at the end of the procedure.</param>
/// <param name="id"></param>
public static void StartProcedure(SKCurve curve, float variable, float time, Action<float> action, Action<float> onFinish = null, string id = "")
{
StartCoroutine(ProcedureCR(curve, variable, 0, 1, time, action, onFinish), true);
}
Since this function persists through time, we should implement it inside a coroutine (ProcedureCR) that takes in the same set of parameters.
private static IEnumerator ProcedureCR(SKCurve curve, float variable, float startValue, float endValue, float timeParam, Action<float> action, Action<float> onFinish)
{
}
Inside the coroutine, first create a "FixedUpdate" function template that works just like the one in Unity's lifecycle.
for (int i = 0; i <= step; i++)
{
yield return new WaitForFixedUpdate();
}
Before that, calculate some of the required data. Note that "variable" is the focus of this function.
variable = startValue;
float step = timeParam / Time.fixedDeltaTime;
float diff = endValue - startValue;
//for...
Then, sample the curve and lerp the variable between startValue(0.0f) and endValue(1.0f). In each round of the loop, invoke the action (where the user actually uses the variable).
for (int i = 0; i <= step; i++)
{
variable = startValue + (SKCurveSampler.SampleCurve(curve, i / step)) * diff;
if (action != null)
action.Invoke(variable);
yield return new WaitForFixedUpdate();
}
After the transition is completed, invoke action and onFinish.
variable = endValue;
if (action != null)
action.Invoke(variable);
if (onFinish != null)
onFinish.Invoke(variable);
Now the tweening function is complete!
public static void StartProcedure(SKCurve curve, float variable, float time, Action<float> action, Action<float> onFinish = null, string id = "")
{
Coroutine cr = StartCoroutine(ProcedureCR(curve, variable, 0, 1, time, action, onFinish), true);
if (id.Length > 0)
{
InsertOrUpdateKeyValueInDictionary(procedureDict, id, cr);
}
}
private static IEnumerator ProcedureCR(SKCurve curve, float variable, float startValue, float endValue, float timeParam, Action<float> action, Action<float> onFinish)
{
variable = startValue;
float step = timeParam / Time.fixedDeltaTime;
float diff = endValue - startValue;
for (int i = 0; i <= step; i++)
{
variable = startValue + (SKCurveSampler.SampleCurve(curve, i / step)) * diff;
if (action != null)
action.Invoke(variable);
yield return new WaitForFixedUpdate();
}
variable = endValue;
if (action != null)
action.Invoke(variable);
if (onFinish != null)
onFinish.Invoke(variable);
}
To use it, simply pass in the parameters:
public GameObject cube;
private float distance = 5;
//Bounce the cube from x=-5 to x=5 in 1.5 seconds.
CommonUtils.StartProcedure(SKCurve.BounceIn, f, 1.5f, (f) =>
{
cube.transform.position = new Vector3(-distance + (2 * distance) * f, cube.transform.position.y, cube.transform.position.z);
});
You can apply this to almost all animation transition effects (smooth loading bars, jumping, scrolling, etc.)!
*These are super useful in game development, remember to implement them on your own!