Unityでボタンやメニューを流れるように表示する

CSS等でよく表現されるメニューやボタンを順番に表示するアニメーションをUnity上で再現する方法を考えてみました。要素を追加すると自動的にアニメーションを開始するCSSのanimationの仕様を見て思いついたものです。


![CascadeMenu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/04f6cb3f-82a5-81aa-bfed-e1a5480d3b20.gif)

ObjectShifter.csをエディターではなく、Awake時にスクリプトでアタッチします

```
    private void Awake()
    {
        ParameterButtons = new ObjectShifter[11];
        ParameterButtons[0] = btn0.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[1] = btn1.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[2] = btn2.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[3] = btn3.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[4] = btn4.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[5] = btn5.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[6] = btn6.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[7] = btn7.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[8] = btn8.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[9] = btn9.gameObject.AddComponent<ObjectShifter>();
        ParameterButtons[10] = btn10.gameObject.AddComponent<ObjectShifter>();

        foreach (ObjectShifter Shifts in ParameterButtons)
        {
            Shifts.SetHidePosition(Vector3.left * 360);
        }
    }

```
SetHidePositionで移動先の位置を設定します

以下のように配列に命令をすると順に表示されます

duration オブジェクトが隠れるまたは表示されるまでの時間
delayper 次のオブジェクトが移動を解するまでの遅延時間

```
    public void ShowParameteres(float duration, float delayper)
    {
        for (int i = 0; i < ParameterButtons.Length; i++)
        {
            ParameterButtons[i].Show(duration, delayper * i);
        }
    }
    public void HideParameters(float duration, float delayper)
    {
        for (int i = 0; i < ParameterButtons.Length; i++)
        {
            ParameterButtons[i].Hide(duration, delayper * i);
        }

    }

```
GameObjectであれば何でもカスケード表示ができます。

```C#:ObjectShifter.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectShifter : MonoBehaviour
{
    private Vector3 DefaultPosition;
    private Vector3 HidePosition;
    private Vector3 PrePosition;
    private Vector3 ToPosition;

    private void Awake()
    {
        DefaultPosition = HidePosition = PrePosition = ToPosition = transform.localPosition;
    }

    private float Delay = 0;
    private float Duration = 0;
    private float CurrentTime = 0;

    public bool toHide = true;
    public bool isHide
    {
        get
        {
            return Vector3.Distance(HidePosition, transform.localPosition) <= Vector3.kEpsilon;
        }
    }

    public void SetHidePosition(Vector3 ShiftPosition)
    {
        HidePosition = DefaultPosition + ShiftPosition;
    }

    public void Show(float duration, float delay = 0)
    {
        Delay = delay;
        Duration = duration;

        CurrentTime = 0;

        PrePosition = transform.localPosition;
        ToPosition = DefaultPosition;
    }

    public void Hide(float duration, float delay = 0)
    {
        Delay = delay;
        Duration = duration;

        CurrentTime = 0;

        PrePosition = transform.localPosition;
        ToPosition = HidePosition;
    }

    public bool isAnimation
    {
        get
        {
            return Duration > 0 && Duration > CurrentTime;
        }
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Delay > 0)
        {
            Delay -= Time.deltaTime;
        }
        else
        {
            if (isAnimation)
            {
                CurrentTime += Time.deltaTime;
                float r = Mathf.Clamp01(CurrentTime / Duration);
                //EaseOut
                r = -r * (r - 2.0f);

                transform.localPosition = Vector3.Lerp(PrePosition, ToPosition, r);
            }
            else
            {
                transform.localPosition = ToPosition;
            }
        }
    }
}

```