Skip to content

Instantly share code, notes, and snippets.

@porglezomp
Last active August 29, 2015 14:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save porglezomp/14e5c49bd7a386fa79cb to your computer and use it in GitHub Desktop.
Save porglezomp/14e5c49bd7a386fa79cb to your computer and use it in GitHub Desktop.
Do parametric animation in Unity3d, inspired by UIView animation in iOS

How to use this

Installation

  1. Copy the PAnim.cs class into your Unity3d project
  2. You're done!

Animating Objects

Animate objects by doing StartCoroutine(PAnim.Animation(...));

  • The duration specifies how long the animation will run for
  • The timing function maps the clock time into a parameter to be used for animation. The simplest, PAnim.Linear will produce a linearly varying parameter in the [0, 1] range. PAnim.EaseInOut will produce a value that accelerates from zero, then decelerates again on [0, 1]. There are more timing functions (but not many yet) and you can also write your own. (See below in "writing timing functions")
  • The animation block does the work of animation. It takes one parameter, a float which will be (if your timing function is well behaved,) zero at the beginning of the animation and one at the end of the animation. Most tasks in the animation block should be performed by setting a value to the result of an interpolation. (If you want interpolations that behave well outside the [0, 1] range, look at Extrap.cs)
  • The completion block will be called when the animation finishes

Writing Animation Blocks

An animation block should usually simply interpolate between values, for instance

transform.position = Extrap.Lerp(Vector3.zero, Vector3.up, t);

will make the object move from the origin to one square above the origin following the curve defined by the parameter

Writing Timing Functions

A timing function controls the character of the animation. A well behaved timing function should:

  • return 0 at the beginning for the animation
  • return 1 at the end of the animation Your timing function takes one float representing the progress of the animation, and should return a float representing the distance the animation has moved. (How far an object is along it's path, how much the rotation has progressed, etc.)
using UnityEngine;
using System.Collections;
public class Animate : MonoBehaviour {
void Start()
{
// Run a 4 second animation with EaseInOut as the timing function, and run the completion handler when it's done
StartCoroutine(PAnim.Animation(4, PAnim.EaseInOut, (t) => {
transform.position = Vector3.Lerp(Vector3.zero, Vector3.up, t);
}, completion: () => {
print("Done!");
}));
}
}
using UnityEngine;
using System.Collections;
using System;
public class PAnim {
public static IEnumerator Animation (float duration, Action<float> animation, Action completion = null)
{
return Animation(duration, Linear, animation, completion: completion);
}
public static IEnumerator Animation (float duration, Func<float, float> timeCurve, Action<float> animation, Action completion = null)
{
float timer = 0;
while (timer < duration) {
float t = timeCurve(timer/duration);
animation(t);
timer += Time.deltaTime;
yield return null;
}
animation(1);
// Don't call it if it's not null
if (completion != null) completion();
}
public static float Linear(float t)
{
return t;
}
// Ease In/Out/InOut functions Referencing http://gizma.com/easing/#cub3
public static float EaseInOut(float t)
{
t *= 2;
if (t < 1) return (t*t*t)/2.0f;
t -= 2;
return (t*t*t + 2)/2.0f;
}
public static float EaseIn(float t)
{
return t*t*t;
}
public static float EaseOut(float t)
{
t--;
return t*t*t + 1;
}
public static Func<float, float> ElasticWithDamping(float zeta)
{
zeta = Mathf.Clamp01(zeta);
return (float t) => {
float z = zeta;
if (t > zeta)
z += Mathf.Pow(t-zeta, 4);
float omega = Mathf.PI * Mathf.Sqrt(1 - z*z);
return 1 - (Mathf.Exp(-t * 10 * z) * Mathf.Cos(omega * t * 10));
};
}
public static float Elastic(float t)
{
float zeta = 0.5f;
if (t > zeta)
zeta += Mathf.Pow(t-zeta, 4);
float omega = Mathf.PI * Mathf.Sqrt(1 - zeta*zeta);
return 1 - (Mathf.Exp(-t * 10 * zeta) * Mathf.Cos(omega * t * 10));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment