かばちんのエンジニアブログ

日々の経験の中で培った内容を備忘録も兼ねて記録していくブログです。少しでも誰かの役に立つために頑張って続けていけたらなと思います。

Automatine を使ってみた

■ピュア C# で動く Timeline

Automatine というピュア C# で動くユーティリティが公開されたので使ってみました。
github.com

■Automatine ってなに?

一言で言うと Timeline のようなものですが、Unity に標準搭載されている Timeline とは違います。
Timeline はどちらかと言うと AdobeFlash に近い感じなのですが、
Automatine はフレーム単位で状態を管理できるステートマシン?(ともちょっと違うかな?)という印象です。

■それって何がいいの?

例えばフレームで管理されている代表例として格ゲーで言うと、
「必殺技を出した時、10フレーム目から20フレーム目まで無敵」とか
「通常技を出した時、5フレーム目から20フレーム目までの間だけ、次の技のコマンド入力を受け付ける」とか
そういった制御が GUI で設定出来るようになっています。

■他にも良い点が

コードがピュア C# & データが JSON というところが便利でよかったです。

リアルタイム通信のゲームを作る時、不正を防ぐためにクライアントと同じ処理をサーバ側でもやるような作りにしたりするのですが
このような手法で開発を行う場合、Unity 自身に搭載されている機能を使ってしまうとサーバ側で同じコードが動かなかったりします。

ピュア C# だと同じ処理をクライアントとサーバで動かせるので、1ソース化ができ開発がとてもやりやすいかつバグりにくくなります。
そしてデータ形式JSON なので、クライアントで動かしているデータをサーバでも使うことができます。

■導入方法

github に UnityPackage が置いてあるので、これを入れるのが手っ取り早いと思います。
github.com

■データの作り方

UntiyPackage を入れると Window -> Automatine というメニューが出てくるので、そこから編集画面を表示できます。
この Automatine 画面で Auto データを作ります。

Auto データとは Automatine で作成するタイムラインデータのことで、
「○フレーム目から○フレーム目までは A という状態」
「○フレーム目から○フレーム目まで、B という Coroutine を毎フレーム実行させる」
といった情報が入っています。

■Autoデータを作ってみる

ここではキャラクターを移動させるような簡単な Auto データ (Locomotion_Auto) を作ってみたいと思います。
Auto (+) から Auto を作成。
f:id:kabatin:20190806141123p:plain

Automatine ウィンドウの空白を右クリックで「Add New Timeline」

Timeline 右クリックで「Add New Tack」
Locomotion はループするようなモーションなので、Unlimited Span (Tack を選択すると Inspector に出てきます)をチェック
f:id:kabatin:20190806141206p:plain

■移動する処理を入れる

Coroutines (+) から Coroutine を生成。
f:id:kabatin:20190806144044g:plain

(Open を押すとエディタが起動してソースを編集できます)
ここで作られた Coroutine が、Tack に設定した帯の長さ(フレーム数)だけ呼ばれます。
最後に [Export As Runtime Code] をクリックすると、動的にクラスを生成してくれます。

■動かしてみる

新しいシーンを作ってテキトーに Cube を作り、以下のコードをアタッチ。

using UnityEngine;
public class Player : MonoBehaviour
{
    Info info;
    Vector3 pos = new Vector3();
    void Start()
    {
        info = new Info();
    }
    void Update()
    {
        var speed = Input.GetAxis("Vertical");
        info.OnUpdate(speed);
        
        pos.x = info.position.x;
        pos.z = info.position.z;
        transform.localPosition = pos;
    }
}

上記コード中の Info クラスは以下のものを使っています。

using Automatine;
public class Info
{
    public Position position = new Position();
    int frame;
    Auto<Position, Position> auto;
    public Info()
    {
        auto = new Locomotion_Auto<Position,Position>(frame, position);
    }
    public void OnUpdate(float speed)
    {
        position.speed = speed;
        auto.Update(frame, position);
        frame++;
    }
}

public class Position
{
    public float x;
    public float z;
    public float speed;
}

「移動する処理を入れる」章で作った Coroutine を以下のコードに修正

using System.Collections;
using Automatine;
public partial class RoutineContexts <InitialParamType, UpdateParamType> : RoutineBase<InitialParamType, UpdateParamType> {
    
    public IEnumerator Locomotion_Coroutine (InitialParamType initialParam) {
        var pos = initialParam as Position;
        while (true)
        {
            pos.z += pos.speed;
            yield return null;
        }
    }
}

実際に表示するものは Player.cs で、位置などの管理は Info.cs に分けられました。
最後に [Export As Data] を押すと JSON が生成されます。
出力先は「Automatine > Runtime > Generated > Json

auto を変更する時は

auto = new Hoge_Auto<Fuga, Fuga>(frame, fuga);

という感じで auto 自体を入れ替えてしまえば良いです。
auto を JSON から読み込む時は

string json = "JSONデータ";
RuntimeAutoData data = AutomatineJsonConverter.JsonToAutoData (json);
auto = Automatine.Auto<Fuga, Fuga>.RuntimeAutoGenerator (data);

とやればいいみたいです。

■まとめ

今回は動かしてみるだけの簡単なものでしたのが、普通にゲームを作るとかなり複雑な状態管理が必要になるので、
そういった時に Automatine の真価が発揮されるのではないかなと思います。