Giter Club home page Giter Club logo

animerx's Introduction

AnimeRx - Rx Tween Animation Library for Unity

  • IObservable<T> Anime.Play(T from, T to, IAnimator animator)

Recommend

This is a library from the days when Task was not yet available in Unity.
I recommend using the Task version.
kyubuns/AnimeTask


Instructions

  • Import UniTask
  • Import AnimeRx
    • Package Manager https://github.com/kyubuns/AnimeRx.git?path=Assets/Plugins/AnimeRx
    • UnityPackage

Examples

Basic

sample1

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

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Motion.Uniform(4f))
    .Subscribe(x => cube.transform.position = x);
    //.SubscribeToPosition(cube);

Method Chain

sample2

(-5,0,0)から(5,0,0)へ移動した後、(0,3,0)に等速で移動。
この方法を用いた場合、1つ目の移動と2つ目の移動で1フレームの間、値の変化が停止します。
スムーズに移動させるには下記のPathの方法を使用してください。

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秒かけて移動。

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

Sleep

sample10

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

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(0f, 0f, 0f), Easing.OutExpo(2f))
    .Sleep(1f)
    .Play(new Vector3(5f, 0f, 0f), Easing.OutExpo(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.InOutSine(6f))
    .SubscribeToPosition(cube);

Combine

sample5

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

var x = Anime.Play(-5f, 5f, Easing.InOutSine(3f));

var y = Anime.Play(0f, 3f, Easing.InOutSine(1.5f))
    .Play(0f, Easing.InOutSine(1.5f));

var z = Anime.Stay(0f);

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

AnimationCurve

sample11

UnityEngine.AnimationCurveを利用して移動。

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

Extensions

sample6

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

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

Circle

sample8

IObservbleを円**に変換。

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

Range / Lerp

sample17

途中まで一緒についていく。
特定の範囲だけついていく。

var flow = Anime.Play(Easing.InOutExpo(2.5f))
    .Stop(0.5f)
    .Play(1.0f, 0.0f, Easing.InOutExpo(2.5f));

flow
    .Range(0.0f, 0.5f)
    .Lerp(new Vector3(-5f, 0f, 0f), new Vector3(0f, 0f, 0f))
    .SubscribeToPosition(cube2);

flow
    .Lerp(new Vector3(-5f, -1f, 0f), new Vector3(5f, -1f, 0f))
    .SubscribeToPosition(cube);

PlayIn/PlayOut/PlayInOut

sample24

Animationから等速**に繋げる。

Anime.PlayIn(-5f, 0f, 5f, Easing.InCubic(1.0f))
    .SubscribeToPositionX(cube);

Delay

sample18

Observable.Delay in UniRx

var circle = Anime.Play(0f, Mathf.PI * 2f, Easing.OutCubic(3f))
    .Select(x => new Vector3(Mathf.Sin(x), Mathf.Cos(x), 0.0f))
    .Select(x => x * 3f);

circle
    .SubscribeToPosition(cube);

circle
    .Delay(0.3f)
    .SubscribeToPosition(cube2);

circle
    .Delay(0.55f)
    .SubscribeToPosition(cube3);

Blend

sample20

2つの移動を足し合わせる。

var circle = Anime
    .Play(Mathf.PI, Mathf.PI * 2f * 3f, Easing.InOutSine(3f))
    .Select(x => new Vector3(Mathf.Sin(x), Mathf.Cos(x), 0f));

var straight = Anime
    .Play(-3f, 3f, Easing.InOutSine(3f))
    .Select(x => new Vector3(0f, x, 0f));

Observable.CombineLatest(circle, straight)
    .Sum()
    .SubscribeToPosition(cube);

WhenAll

sample9

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

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

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

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

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

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

Loop, Repeat

var disposable = Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Motion.Uniform(5f))
    .Repeat() // infinite loop
    .SubscribeToPosition(cube1);

Observable.Timer(TimeSpan.FromSeconds(5)).Subscribe(_ =>
{
    Debug.Log("Stop!");
    disposable.Dispose();
});

Create your self!

自由に拡張できるインターフェイスが準備されています。

private class ShuffleAnimator : IAnimator
{
    private readonly float duration;

    public ShuffleAnimator(float duration)
    {
        this.duration = duration;
    }

    public float CalcFinishTime(float distance)
    {
        return duration;
    }

    public float CalcPosition(float time, float distance)
    {
        return Random.Range(0f, 1f);
    }
}

private void Shuffle()
{
    var shuffleX = Anime.Play(-1f, 1f, new ShuffleAnimator(3f));
    var shuffleY = Anime.Play(-1f, 1f, new ShuffleAnimator(3f));

    Observable.CombineLatest(shuffleX, shuffleY)
        .Select(x => new Vector3(x[0], x[1]))
        .SubscribeToPosition(cube);
}

Selecting Card

var selectingCard = new ReactiveProperty<Image>(null);
foreach (var card in cards)
{
    var cardRectTransform = card.GetComponent<RectTransform>();
    card.OnPointerClickAsObservable().Subscribe(x => selectingCard.Value = card).AddTo(card);

    var gauge = new ReactiveProperty<float>(0f);
    selectingCard
        .Select(x =>
        {
            var isSelecting = x == card;
            var target = isSelecting ? 1.0f : 0.0f;
            var speed = isSelecting ? 1.0f : 2.0f; // 戻る時は2倍速
            card.color = isSelecting ? Color.yellow : Color.white;
            return Anime.Play(gauge.Value, target, Motion.Uniform(speed));
        })
        .Switch()
        .Subscribe(x => gauge.Value = x);

    gauge
        .Subscribe(x =>
        {
            var p = cardRectTransform.localPosition;
            p.y = OutCirc.Calc(x) * SelectingY;
            cardRectTransform.localPosition = p;
        })
        .AddTo(card);
}

Requirements

  • Unity 2017.1 or later.
    • checked by 2019
  • Support .net3.5 and .net4.6

Special thanks

License

MIT License (see LICENSE)

animerx's People

Contributors

kaw0 avatar kyubuns avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

animerx's Issues

Shake or Punch?

Hi, fantastic library, planing to replace the one we use currently with AnimeRx because of great UniRx integration. Question: is the support for "higher level" tweens like Punch or Shake planned?

[fix bug] fix sleep not working properly

Look at the code below, It seems that Sleep did not work as expected

Anime.Play(new Vector3(-5f, 0f, 0f), new Vector3(5f, 0f, 0f), Easing.OutExpo(2f))
    .Sleep(3f)
    .Play(new Vector3(-5f, 0f, 0f), Easing.OutExpo(2f))
    .SubscribeToPosition(cube);

it should have waited here for 1 second after the cube moved to position 5f before moving to position -5. but it will move immediately to position Vector3 (0f, 0f, 0f) and wait for 1 second here then move to position -5, by default (Vector3) returns Vector3.zero

        public static IObservable<T> Sleep<T>(float duration, IScheduler scheduler)
        {
            return SleepInternal(duration, scheduler).Select(_ => default(T));
        }

        public static IObservable<T> Sleep<T>(float duration, T value, IScheduler scheduler)
        {
            return SleepInternal(duration, scheduler).Select(_ => default(T)).Stay(value);
        }

default (T) needs to be replaced

I write it into something like:

        public static IObservable<T> Sleep<T>(float duration, T value)
        {
            return Sleep(duration, value, DefaultScheduler);
        }

        public static IObservable<T> Sleep<T>(float duration, T value, IScheduler scheduler)
        {
            return SleepInternal(duration, scheduler).Select(_ => value);
        }

*Full code

public static partial class Anime
    {
        public static IObservable<Unit> Sleep(float duration)
        {
            return Sleep(duration, DefaultScheduler);
        }

        public static IObservable<Unit> Sleep(float duration, IScheduler scheduler)
        {
            return SleepInternal(duration, scheduler);
        }

        public static IObservable<T> Sleep<T>(float duration, T value)
        {
            return Sleep(duration, value, DefaultScheduler);
        }

        public static IObservable<T> Sleep<T>(float duration, T value, IScheduler scheduler)
        {
            return SleepInternal(duration, scheduler).Select(_ => value);
        }

        public static IObservable<T> Sleep<T>(this IObservable<T> self, float duration)
        {
            return self.Select(x => self.Concat(Sleep(duration, x))).Switch();
        }

        public static IObservable<T> Sleep<T>(this IObservable<T> self, float duration, IScheduler scheduler)
        {
            return self.Select(x => self.Concat(Sleep(duration, x, scheduler))).Switch();
        }

        public static IObservable<T> Sleep<T>(this IObservable<T> self, float duration, T value)
        {
            return self.Concat(Sleep(duration, value));
        }

        public static IObservable<T> Sleep<T>(this IObservable<T> self, float duration, T value, IScheduler scheduler)
        {
            return self.Concat(Sleep(duration, value, scheduler));
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.