AnimeRx - Unity + RxでTweenアニメーションをつける!

github.com

UniRxガンガン使ってる方向けのTweenアニメーションライブラリです。

コンセプト

  • アニメーションライブラリといいつつも、TransformやGameObjectは握らず、
    素直に IObservable(float,Vector2,Vector3)を操作するライブラリ。
    (下記サンプル内の"Combine"や"Advanced - Circle"を見ていただければ柔軟さがわかると思います。)
  • Easingは一通り実装済み。
  • 「aからbにn秒で移動」だけでなく「aからbに速度vで移動」の指定が可能。
  • スケジューラーも自分で書けるので「Time.time」「Time.unscaledTime」だけでなく独自のタイマーで動かすことが可能。

リポジトリ

https://github.com/kyubuns/AnimeRx

基本

  • Anime.PlayIObservable<Vector3> を準備
  • SubscribeToPosition(cube) などを使ってtransformに代入

サンプル

Start

sample1

(-5,0,0)から(5,0,0)へ、秒速4mで移動。

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Motion.Uniform(4f))
    .SubscribeToPosition(cube);

SubscribeToPositionは以下と同義です。

    .Subscribe(x => cube.transform.position = x);

他にもSubscribeToLocalPosition, SubscribeToLocalScaleや、 IObservable<float> を取るSubscribeToPositionXなどなど諸々準備してあります。

Method Chain

sample2

(-5,0,0)から(5,0,0)へ移動した後、(0,3,0)に等速で移動。 メソッドチェーンでガンガン次の動きを書いていけます。

var animator = Motion.Uniform(5f);
Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), animator)
    .Play(new Vector3(0f, 3f, 0f), animator)
    .SubscribeToPosition(cube);

Easing

sample3

EaseOutQuadで2秒かけて移動。 Easingは一通り実装済み。

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Easing.EaseOutQuad(TimeSpan.FromSeconds(2f)))
    .SubscribeToPosition(cube);

Wait

sample10

移動した後、1秒まって再度動き出す。

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(0f, 0f, 0f), Easing.EaseOutExpo(TimeSpan.FromSeconds(2f)))
    .Wait(TimeSpan.FromSeconds(1f))
    .Play(new Vector3(5f, 0f, 0f), Easing.EaseOutExpo(TimeSpan.FromSeconds(2f)))
    .SubscribeToPosition(cube);

Path

sample4

指定したpositionに順番に移動。

var positions = new[]
{
    new Vector3(-5f, 0f, 0f),
    new Vector3(0f, 3f, 0f),
    new Vector3(5f, 0f, 0f),
    new Vector3(0f, -3f, 0f),
    new Vector3(-5f, 0f, 0f),
};

Anime.Play(positions, Easing.EaseInOutSine(TimeSpan.FromSeconds(6f)))
    .SubscribeToPosition(cube);

Combine

sample5

x, y, zの各座標を別々にアニメーションさせて合成。

var x = Anime.Play(-5f, 5f, Easing.EaseInOutSine(TimeSpan.FromSeconds(3f)));

var y = Anime.Play(0f, 3f, Easing.EaseInOutSine(TimeSpan.FromSeconds(1.5f)))
    .Play(0f, Easing.EaseInOutSine(TimeSpan.FromSeconds(1.5f)));

var z = Anime.Stay(0f);

Observable.CombineLatest(x, y, z)
    .SubscribeToPosition(cube);

Extensions

sample6

cube.transform.positionから(3,3,0)へ移動。

cube.transform.position
    .Play(new Vector3(3f, 3f, 0f), Easing.EaseOutBack(TimeSpan.FromSeconds(2f)))
    .SubscribeToPosition(cube);

Advanced - Circle

sample8

IObservbleを円運動に変換。

Anime.Play(0f, Mathf.PI * 2f, Easing.EaseOutCubic(TimeSpan.FromSeconds(3f)))
    .Select(x => new Vector3(Mathf.Sin(x), Mathf.Cos(x), 0.0f))
    .Select(x => x * 3f)
    .SubscribeToPosition(cube);

Advanced - Timing

sample9

WhenAllを使ってアニメーションのタイミングを合わせる。

var leftCube1 = Anime
    .Play(new Vector3(-5f, 0f, 0f), new Vector3(-0.5f, 0f, 0f), Easing.Linear(TimeSpan.FromSeconds(2.5f)))
    .DoToPosition(cube);

var rightCube1 = Anime
    .Play(new Vector3(5f, 0f, 0f), new Vector3(0.5f, 0f, 0f), Easing.EaseOutCubic(TimeSpan.FromSeconds(1f)))
    .DoToPosition(cube2);

var leftCube2 = Anime
    .Play(new Vector3(-0.5f, 0f, 0f), new Vector3(-0.5f, 3f, 0f), Easing.EaseOutCubic(TimeSpan.FromSeconds(1f)))
    .DoToPosition(cube);

var rightCube2 = Anime
    .Play(new Vector3(0.5f, 0f, 0f), new Vector3(0.5f, 3f, 0f), Easing.EaseOutCubic(TimeSpan.FromSeconds(1f)))
    .DoToPosition(cube2);

Observable.WhenAll(leftCube1, rightCube1)
    .ContinueWith(Observable.WhenAll(leftCube2, rightCube2))
    .Subscribe();

AnimationCurve

sample11

UnityEngine.AnimationCurveを利用して移動。

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Motion.From(curve, TimeSpan.FromSeconds(3f)))
    .SubscribeToPosition(cube);

HPゲージが徐々に減る