Tween

Animate anything with style and just one line of code.

With Tween in your arsenal you can move, rotate, scale, shake, fade, colorize and anything else with a very easy to use interface that allows you to add polish and effects with very little effort and a boat-load of control. Tween’s DNA comes from iTween and is created by the same developer. If you aren’t familiar with iTween it has been used by thousands of developers from all over the globe from the beginner to the AAA game studio and is even used in Minecraft! You can think of Tween as iTween with a college degree and a blackbelt in ass-kicking. Tween is easier, faster, more powerful and was built from the ground up to handle anything you need it for.

Hello World!

Tween’s syntax is very similar to a command you’d issue for someone to carry out for you:

“Hey Tween, please move the position of this transform from 0,0,0 to 0,1,0 in 1 second and don’t delay."

which, when coded, translates to

Tween.Position (transform, new Vector3 (0,0,0), new Vector3 (0,1,0), 1, 0);

which looks like

or

“Hey Tween, please rotate this transform to 0,90,0 in 1 second, delay for 1 second and accelerate and decelerate as you go."

which translates to

Tween.Rotation (transform, new Vector3 (0,90,0), 1, 1, Tween.EaseInOutStrong);

which looks like

Getting the feel just right

Tween utilizes Unity’s built-in AnimationCurves for controlling the easing it does. Out of the box Tween comes with a collection of ease curves that are likely to look "just right" in almost any situation.

However, if you need something custom to get the feel of your animation just right, Tween has your back. To utilize custom AnimationCurves for easing in Tween simply make a public AnimationCurve in your script, edit it in the Unity inspector and then feed it into your tween call.

using UnityEngine;
using Pixelplacement;

public class TweenExample : MonoBehaviour
{
	public AnimationCurve myCurve;

	void Awake ()
	{
		Tween.LocalPosition (transform, Vector3.up, 1, 0, myCurve);
	}
}

Looping

Tweens can be automatically repeated in two ways: looped and ping pong. Simply add the style of loop you want after your ease curve when making a Tween call.

using UnityEngine;
using Pixelplacement;

public class TweenExample : MonoBehaviour
{
	void Awake ()
	{
		Tween.LocalRotation (transform, new Vector3 (0, 90, 0), 2, 0, Tween.EaseInOutStrong, Tween.LoopType.PingPong);
	}
}

Reacting to status

Knowing when a Tween finishes or when a delayed Tween starts is helpful for progressing logic, firing off effects, triggering audio effects, transitioning scenes and more. Tween allows for 2 optional callbacks to run code when things happen or stop happening.

using UnityEngine;
using Pixelplacement;

public class TweenExample : MonoBehaviour
{
	void Awake ()
	{
		Tween.LocalScale (transform, Vector3.zero, Vector3.one, 2, 1, Tween.EaseOutBack, Tween.LoopType.None, HandleTweenStarted, HandleTweenFinished);
	}

	void HandleTweenStarted ()
	{
		Debug.Log ("This tween delayed for 1 second before it just started.");
	}

	void HandleTweenFinished ()
	{
		Debug.Log ("This tween just finished!");
	}
    
}

You can even use Lambda Expressions in your callbacks if you have quick code to call to avoid the need for a complete function to handle status.

using UnityEngine;
using Pixelplacement;

public class TweenLambdaExpressionCallback : MonoBehaviour
{
	public Transform myTarget;

	void Awake ()
	{
		Tween.LocalScale (myTarget, Vector3.zero, 2, 0, Tween.EaseInBack, Tween.LoopType.None, null, () => Destroy (myTarget.gameObject));
	}
}

Monitoring status

Though less efficient than utilizing Tween's status callbacks, it is also possible to query a Tween for status.

using UnityEngine;
using Pixelplacement;
using Pixelplacement.TweenSystem;

public class TweenStatus : MonoBehaviour
{
	TweenBase myTween;

	void Awake ()
	{
		myTween = Tween.Position (transform, Vector3.up, 3, .5f, Tween.EaseInOutStrong);
	}

	void Update ()
	{
		Debug.Log (myTween.Status);	
	}
}

Timescale

Unity’s timescale can be adjusted to pause a game, enter slow motion or go into hyper speed. Sometimes you will want your Tweens to respect timescale differently depending on how they are used. For instance, if you are using Tween to animate a pause menu then you certainly do not want those Tweens respecting timescale or they simply won’t move once a game drops timescale to 0. By default all Tweens will obey Unity’s timescale but you can easily change that with the last, optional parameter of a Tween.

using UnityEngine;
using Pixelplacement;

public class TweenExample : MonoBehaviour
{
	void Awake ()
	{
		Time.timeScale = 0;
		Tween.LocalPosition (transform, new Vector3 (0, 1, 0), 2, 0, Tween.EaseInOutStrong, Tween.LoopType.PingPong, null, null, false);
	}
}

Physics

If you are trying to animate an object with Tween that has a rigidbody attached be sure to set the rigidbody's "isKinematic" flag to true beforehand.

Custom control

Tween has a large collection of built-in controls for animating things but sometimes you need something custom. Using a special kind of Tween called a Value you can animate or use these variations for controlling anything that Tween can’t normally do. Value tweens simply utilize an additional callback that provides the currently animating value for use as needed. Value has variations that provide callbacks that send Rect, Vector2, Vector3, Vector4, Float, Int or Color.

using UnityEngine;
using Pixelplacement;

public class TweenExample : MonoBehaviour
{
	float _buttonWidth;
	float _minWidth = 100;
	float _maxWidth = 160;

	void Awake ()
	{
		Tween.Value (_minWidth, _maxWidth, HandleButtonWidthChange, .5f, 0, Tween.EaseInOut, Tween.LoopType.PingPong);
	}

	void HandleButtonWidthChange (float value)
	{
		_buttonWidth = value;
	}

	void OnGUI ()
	{
		GUILayout.Button ("BUY NOW!", GUILayout.Width (_buttonWidth));
	}
}

Variations

Tween has two variations for each type of animation it allows: destination-only and origination-to-destination. These variations behave very differently and it’s important to know how and when to use each.

Destination-only Tweens only specify an ending value. These Tweens will simply use the current state or values as the beginning of their animation.

Tween.Position (transform, new Vector3 (1, 0, 0), 1, 0);

Origination-to-destination tweens allow for a starting and ending value. In addition to specifically setting a starting value these Tweens behave slightly different when delayed than destination-only Tweens do.

Tween.Position (transform, Vector3.zero, new Vector3 (1, 0, 0), 1, 0);

When delaying a origination-to-destination Tween it is important to note that the target will be immediately set to the provided start value and will remain at this value until the delay expires. Destination-only Tweens will begin at their current values as soon as a delay expires making them better suited for dynamic situations.

Controlling a tween

If you ever need to stop, start, cancel, finish, rewind or check status of a tween you will need to include the Pixelplacement.TweenSystem namespace.

Each tween call you make will return a TweenBase object which you can use to control the tween.

using UnityEngine;
using Pixelplacement;
using Pixelplacement.TweenSystem;

public class TweenExample : MonoBehaviour
{
	TweenBase tween;

	void Awake ()
	{
		tween = Tween.Position (transform, Vector3.zero, Vector3.up, 1, 0);
	}

	void OnGUI ()
	{
		if (GUILayout.Button ("Start")) tween.Start ();
		if (GUILayout.Button ("Cancel")) tween.Cancel ();
		if (GUILayout.Button ("Finish")) tween.Finish ();
		if (GUILayout.Button ("Rewind")) tween.Rewind ();
	}
}

Sequencing tweens

Creating complex animations are easy with multiple tweens and usage of the delay property.

The follwing code demonstrates how to perform the loading bar animation shown above with easy maintenance of delay.

using UnityEngine;
using UnityEngine.UI;
using Pixelplacement;

public class Sequence : MonoBehaviour
{
	public Image gutter;
	public Image bar;

	private float _delay;

	private void Awake()
	{
		//determine our gutter tween values:
		Vector2 gutterStartSize = new Vector2(0, gutter.rectTransform.sizeDelta.y);
		Vector2 gutterEndSize = gutter.rectTransform.sizeDelta;

		//tween our gutter in:
		Tween.Size(gutter.rectTransform, gutterStartSize, gutterEndSize, .5f, 0, Tween.EaseInOutStrong);

		//update delay:
		_delay += .5f;

		//determine our bar tween values:
		Vector2 barStartSize = new Vector2(0, bar.rectTransform.sizeDelta.y);
		Vector2 barEndSize = bar.rectTransform.sizeDelta;

		//tween our bar in:
		Tween.Size(bar.rectTransform, barStartSize, barEndSize, 1, _delay, Tween.EaseInOutStrong);

		//update delay:
		_delay += 1;

		//fade out the bar (notice we use the version of Tween here that does not use a start value - this is key for sequencing the "current" of something):
		Tween.Color(bar, Color.clear, .5f, _delay);

		//update delay:
		_delay += .5f;

		//shrink the gutter (notice we use the version of Tween here that does not use a start value - this is key for sequencing the "current" of something):
		Tween.Size(gutter.rectTransform, gutterStartSize, .5f, _delay, Tween.EaseInOutStrong);
	}
}