Skip to content

Instantly share code, notes, and snippets.

@AliFlux
Last active December 17, 2017 01:46
Show Gist options
  • Save AliFlux/7c40bda68f08930b554cf754d896b600 to your computer and use it in GitHub Desktop.
Save AliFlux/7c40bda68f08930b554cf754d896b600 to your computer and use it in GitHub Desktop.
Fluent Animation documentation

Fluent.Animation Documentation

A Unity3D plugin that makes it incredibly easy animate almost anything using fluent functions. Fluent Animation takes a procedural/functional way of solving the decade old animation queue and callback hell problem.

Download Now

Features

  • Move, rotate, scale almost anything
  • Execute animations in parallel
  • Comes with 31 easing effects
  • Support for custom easing effect
  • Animate objects on a set of way points
  • Animate custom components
  • Animate custom fields/properties
  • Extend class to add more features
  • Customize animation update type
  • Loop, control, or jump to specific animation
  • Bezier, Spline and Linear waypoint paths
  • Comes with 5 free easy to learn demos

Get Started

Import the Fluent Animation package into your project and explore the directories.

Learn by example

Try out the given demos inside the FluentAnimation\Demo\Scene folder. In each of the demos, there is a scene, and a custom script with the same name attached to the MainCamera. Open that script to see how the demo works.

Learn by code

Animating a simple GameObject

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0), 3f)
  .RotateTo(Quaternion.Euler(0, 90, 30), 3f);

So what happened here? Well, the New() method created a new animation component and attached it to a dummy game object. The With method made sure that all next animations are applied to the given gameObject. The MoveTo and RotateTo functions animated the position and rotation of the gameObject in series in 3 seconds.

The animations were queued. The rotation occured after the movement, and that's the beauty of procedural/fluent scripting.

Animating in parallel

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0), 2f)
  .Parallel(
    Fluent.Animation.New().MoveTo(new Vector3(100, 0, 100)),
    Fluent.Animation.New().RotateTo(Quaternion.Euler(0, 90, 0))
  )
  .MoveTo(new Vector3(0,0,0), 1f);

So what happened now? Well...

  • The first MoveTo moved the object
  • After that, the Parallel function started off 2 parallel animations (MoveTo and RotateTo)
  • And then, the MoveTo took the object back to 0,0,0

This shows how animations can be triggered in either series, parallel, or a combination of both.

Animation with Easing

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0), 3f, Fluent.Animation.LookType.Interpolate, Fluent.Easing.Circular.Out);

You can make use of over 30 easing functions to make your animations feel more natural. The easing list is given in the references section. The LookType tells how the object rotates during movement.

Execute custom functions during animation queue

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0), 3f)
  .Then(() => {
    // do something 
  })
  .RotateBy(Quaternion.Euler(0,90,45))
  .Then(() => {
    // do something again 
  });

Then can be used to trigger custom functions.

Looping and controlling the animation

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0))
  .RotateBy(Quaternion.Euler(0, 90, 90))
  .Loop();

When the rotation has ended, the Loop statement restarts the whole animation queue. If you want to go back to a specific animation step, you can use Label and Goto statements.

Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0))
  .Label("Good Game")
  .RotateBy(Quaternion.Euler(0, 90, 90))
  .Goto("Good Game");

The Label function puts a point in a queue. The Goto statement goes back to the point defined by the label (in this case "Good Game"). You can also use Goto statement to goto a certain step (in past or future) if a condition is met, using GotoIf.

Animating custom components or properties

Fluent gives the ability to animate almost anything we like. Let's try animating a customProperty of a CustomComponent.

Fluent.Animation.New()
  .AnimateProperty(gameObject.GetComponent<CustomComponent>(), 'customProperty', 20f, 30f, 2f)

This will animate the customProperty from 20f to 30f in 2 seconds. This code also works on built-in components and properties. AnimatePropertyBy can be used if you don't want to specify the starting value.

Animating an object on a path

Open the PathDemo to see how an object can follow a given path. Here's how you can use paths for animating your own objects.

  1. Create an empty GameObject and add Fluent.Path component to it.
  2. Add several empty game objects with Fluent.PathPoint component, within that gameObject.
  3. Drag the child gameObjects around and you would observe a path between those points.
  4. Change the PathInterpolation property of the parent Path component to your needs.
  5. Use the following script in a new component:
Fluent.Animation.New ()
  .With (gameObject)
  .MoveOnPath (pathObject.GetComponent<Fluent.Path>(), Fluent.Animation.LookType.Forward, 3f)

This is going to move a specific object on a path, looking forward, within 3 seconds. If you want to keep it moving forever, you can add Loop() at the end of the animation queue, and set the ConnectedTerminals property of Path to true.

Note:

If you change position or rotation of any PathPoint after the during the game, make sure you call the Bake() function of Path.

Event handling

You can make use of certain events to make your animation queue even more powerful.

var animation = Fluent.Animation.New()
  .With(gameObject)
  .MoveTo(new Vector3(0, 100, 0), 3f);

animation.AnimationEnded += animationEnded;
private void animationEnded(Fluent.Animation animation) {
    //  called when the animation queue has ended
}

Check out the reference for the events list.


API Reference

Fluent.Animation Class

Static Methods

New*()*

Creates a new Fluent.Animation component and attaches it to a dummy GameObject.

New*(GameObject)*

Creates a new Fluent.Animation component and attaches it to the specified GameObject.

ClearAll*()*

Removes all Fluent.Animation components from the dummy GameObject.

ClearAll*(GameObject)*

Removes all Fluent.Animation components from the specific GameObject.

Fluent Methods

These methods can be used in a chain form. And are triggered when the previous animation steps are completed.

Then*(Action)*

Performs an action.

WaitFor*(float seconds)*

Waits for given # of seconds.

WaitUntil*(TaskCondition)*

Waits until a delegate/func returns true.

Parallel*(... Fluent.Animation)*

Executes given animations in parallel.

Loop*()*

Restarts the animation queue.

LoopIf*(TaskCondition)*

Restarts the animation queue if the condition is met.

With*(GameObject)*

Runs all subsequent animations in the given GameObject.

MoveTo*(Vector3 destination, float duration = 1f, LookType lookRotation = LookType.Interpolate, Func<float, float> easing = null)*

Moves the selected gameObject to a destination.

MoveBy*(Vector3 offset, float duration = 1f, LookType lookRotation = LookType.Interpolate, Func<float, float> easing = null)*

Moves the selected gameObject by offset.

MoveBy*(float distance, Quaternion angle, float duration = 1f, LookType lookRotation = LookType.Interpolate, Func<float, float> easing = null)*

Moves the selected gameObject using angle/direction and distance.

Move<Direction>(float distance, float duration = 1f, LookType lookRotation = LookType.Interpolate, Func<float, float> easing = null)

Makes the object move forward, backward, up, down, left, or right relative to world rotation.

MoveRelatively<Direction>(float distance, float duration = 1f, LookType lookRotation = LookType.Interpolate, Func<float, float> easing = null)

Makes the object move forward, backward, up, down, left, or right relative to it's own rotation.

RotateTo*(Quaternion expectedRotation, float duration = 1f, Func<float, float> easing = null)*

Rotates to the given rotation.

RotateBy*(Quaternion deltaRotation, float duration = 1f, Func<float, float> easing = null)*

Rotates by the given rotation offset.

LookTo*(Vector3 pointOfInterest, float duration = 1f, Func<float, float> easing = null)*

Looks to a given point of interest.

ScaleTo*(Vector3 expectedScale, float duration = 1f, Func<float, float> easing = null)*

Scales the object to the given scale.

ScaleBy*(Vector3 deltaScale, float duration = 1f, Func<float, float> easing = null)*

Scales the object by the given scale offset.

AnimateProperty*(object host, string propertyName, object startValue, object endValue, float duration, Func<float, float> easing = null)*

Animates a custom property of a host, from startValue, to endValue, in fiven duration using given easing function.

AnimateProperty*(object host, string propertyName, object endValue, float duration, Func<float, float> easing = null)*

Animates a custom property of a host, given the endValue only.

AnimatePropertyBy*(object host, string propertyName, object offset, float duration = 1f, Func<float, float> easing = null)*

Animates a custom property by an offset.

AnimateValue*(T startValue, T endValue, Action<T, float> callback, float duration = 1f, Func<float, float> easing = null)*

Animates a new value from startValue to endValue. The callback is triggered on each step and is used to make use of the value being animated.

MoveOnPath*(Path path, LookType lookRotation = LookType.Forward, float speedMultiplier = 1f, Func<float, float> easing = null)*

Moves a GameObject on the given path.

RotateOnPath*(Path path, float speedMultiplier = 1f, Func<float, float> easing = null)*

Rotates the given GameObject according to the rotation of PathPoints in the given path.

ChangeUpdateType*(UpdateType)*

Changes the update type for all following animations. Useful for animating cameras, physics, and custom dynamics.

Log*(string message)*

Logs a message to the console when the step occurs.

Label*(string label)*

Places a label in that point of animation queue.

Goto*(string label)*

Goes to a specific point in queue defined by the label.

GotoIf*(string label, TaskCondition)*

Goes to a certain point if a condition has been met.

Control Methods

These methods are used to control the state of the animation queue, or extend the Fluent.Animation with new functionality. They should not be used in a chained way.

Suspend*()*

Temporarily pauses the animation, and all sub/parallel animations.

Resume*()*

Resumes a suspended animation queue.

Restart*()*

Restarts the animation queue.

GotoIndex*(int index)*

Goes to a specific index in a queue.

Dequeue*()*

Removes the animation step from front of the queue.

Enqueue*(Step step)*

Adds a new animation step to the queue.

NewStep*() : Step*

Creates a new animation step.

Events

Refer to the event handling example above to see how to use these.

AnimationEnded*(Animation)*

Triggers when the animation queue has ended has ended.

AnimationStopped*(Animation)*

Triggers when the animation queue has ended has been stopped.

AnimationSuspended*(Animation)*

Triggers when the animation queue has been paused/suspended.

AnimationResumed*(Animation)*

Triggers when a suspended animation queue has been resumed.

PathPointEnter*(GameObject gameObject, PathPoint pathPoint)*

Triggered when a PathPoint is entered by a gameObject during MoveOnPath animation.

PathPointMove*(GameObject gameObject, PathPoint pathPoint, float progress)*

Triggered when a gameObject is moving on PathPoint during MoveOnPath animation.

Fluent.Easing Class

Check out the easing example above to see how to use each easing function, and refer to Easings.net to see how each function feels like.

- Linear
- Quadratic.In
- Quadratic.Out
- Quadratic.InOut
- Cubic.In
- Cubic.Out
- Cubic.InOut
- Quartic.In
- Quartic.Out
- Quartic.InOut
- Quintic.In
- Quintic.Out
- Quintic.InOut
- Sinusoidal.In
- Sinusoidal.Out
- Sinusoidal.InOut
- Exponential.In
- Exponential.Out
- Exponential.InOut
- Circular.In
- Circular.Out
- Circular.InOut
- Elastic.In
- Elastic.Out
- Elastic.InOut
- Back.In
- Back.Out
- Back.InOut
- Bounce.In
- Bounce.Out
- Bounce.InOut

Fluent.Path Class

Instance Methods

Bake*()*

Bakes a path according to each point. Should be called as soon as any PathPoint is changed.

Properties

ConnectedTerminals*: bool*

Joins the start and end points of this path. Used to loop animations.

PathInterpolation*: enum*

Tells how the object would move on this path. It can be:

  • Linear (in a straight point to point way)
  • Bezier (in a curved fashion, object may not pass through every point)
  • Spline (same as Bezier, but object would definititely pass through every point)

Fluent.PathPoint Class

Events

OnEnter*(PathPoint)*

Triggered when this PathPoint is entered by any object.

OnMove*(PathPoint, float progress)*

Triggered when a gameObject is moving on this PathPoint. progress can be from 0 to 1.

Properties

Duration*: float*

Time it takes to reach this PathPoint in seconds.

Key*: string*

Used to store additional info on this point.

@mburro
Copy link

mburro commented Dec 16, 2017

Hi, i have purchased this asset, and like it so far; but i have encountered a problem with Parallel()

  1. Parallel will not work, when i try to parallel two MoveBy Animations lets say with one along the x, and the other one along the z axis with different Easing Functions. In this case it will only do the second Animation and dismiss the first one.

After each Parallel i need to recall the .with(Object) Method, why is this ?

Thanks in advantage, and for the asset. Keep up the good work!

@beardordie
Copy link

I like the asset. I would appreciate more examples of real-world use cases, especially including LookAt, RotateOnPath, and Events. I haven't tried Parallel yet, but if mburro's comment is accurate, a fix for that is appreciated as well. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment