【TinyUnity】ProjectTiny0.20を触ってみよう! #2 入力受付と移動編

この記事は前回の記事を読んでいることを前提として書かれています。

さて、前回はTinyUnityのセットアップを行い、Cubeをワールド上に配置するところまでを行いました。

今回は、

入力の受付移動

について書いていきます。

ゲームにはプレイヤーからの入力を受け取るシステムが必ず必要になります。

操作を必要とせず、眺めたり待つだけのいわば放置ゲーと言われるジャンルのゲームも存在しますが、それでも画面内のボタンを押すくらいの操作は必要になります。

そのため、入力を受け取る方法を知ることは最重要であると言えます。

移動に関しても同様で、オブジェクトの移動が無い3Dゲームというのはほぼ存在しません。

つまり、入力の受付と移動方法はTinyUnityでゲームを作ることにおいて必ず最初に学ぶべき知識であるといえます。

何故わざわざ、TinyUnityの記事として入力の受付と移動について書いているのかというと、PureECS構成や、TinyUnityである都合上、かなり独特な書き方をするためです。

Entityの操作はTinyUnityというよりは、ECSに関する知識が必要となります。

とはいえ、原理は簡単です。

Entityの操作はすべてComponentSystemに記述する

このことさえ理解していれば問題なく処理を書くことができます。

それでは早速始めていきましょう。

オブジェクトを回転させてみよう!

まずは、C#スクリプトを作っておきましょう

今回は「RotateSystem」という名前で作成しました。

そうしたら、以下のコードに全体を書き換えてください

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;

public class RotateSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        Entities.ForEach((ref Rotation rot) => 
        {
            rot.Value = math.mul(rot.Value, quaternion.RotateY(dt * 10));
        });
    }
}

以上のコードを書き込んだら、保存して、実行ボタンを押してみてください!

おそらく、ワールドに設置されたEntityが回転し始めるかと思います。

では、なぜこのような結果が表れるのか、コードを解説していきます。

public class RotateSystem : ComponentSystem

この行でComponentSystemを継承することでSystemであることを宣言しています

protected override void OnUpdate(){}

通常のUnityでのUpdate関数です。この中に処理を書いていきます

        Entities.ForEach((ref Rotation rot) => {});

この行が一番大事です。

OnUpdateは毎フレームは知るわけですが、まだ、どのEntityを操作するかの指定がされていません。それがこのEntities.ForEacch()になります。

Entities.ForEach( (ref 操作対象にしたいComponent ) => { 指定したデータに対する処理 });

このような感じ。

ここまで読めば、先ほどのスクリプトが十分読めると思います。

なんでSystemをSceneに置いてないのにCubeが動いているの?

という理由は

ECSでは何の設定もしないと自動的に記述しているSystemはすべて実行される

ためです。この辺りに関してはまた機会があれば説明します。

オブジェクトを移動させてみよう!

以下のように書き替えます

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;

public class RotateSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        Entities.ForEach((ref Rotation rot, ref Translation translation) => 
        {
            rot.Value = math.mul(rot.Value, quaternion.RotateY(10*dt));
            translation.Value.z += 10 * dt;
        });
    }
}

ForEachの対象ComponentDataにTranslationが追加されました。

Translationは通常のUnityでのTransform.Positionです。

処理内ではTranslation.Positionの値を直接プラスしています。

後は実行すれば回転しながら奥にオブジェクトが進んでいくと思います。

以上が、移動と回転の方法になります。

入力を受け取ろう!

TinyUnityでは入力の受け取り方も独特です。

先ほどのスクリプトを以下のように書き替えましょう。

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using Unity.Tiny.Input;

public class RotateSystem : ComponentSystem
{
    private InputSystem Input => World.GetExistingSystem<InputSystem>();

    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        var InputFlag = Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0) ||Input.TouchCount() > 0;
        Entities.ForEach((ref Rotation rot, ref Translation translation) => 
        {
            if (InputFlag)
            {
                rot.Value = math.mul(rot.Value, quaternion.RotateY(10 * dt));
                translation.Value.z += 10 * dt;
            }
        });
    }
}

usingにUnity.Tiny.Inputが追加されている点に注意してください。

private InputSystem Input => World.GetExistingSystem<InputSystem>();

TinyUnityで入力を受け取るには、独自のInputSystemを利用しなければなりません。

この行ではその独自のInputSystemを取得してInputSystem型の変数に格納しています。

World.GetExistingSystem<T>();

は別のSystemをキャプチャすることができる関数です。

返り値は実行中の指定型のSystem本体となります。

var InputFlag = Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0) ||Input.TouchCount() > 0;

ここの説明はもはや不要かと思いますが、一応説明します。

一度InputSystemをキャプチャしてしまえばあとは通常のUnity同様のInput同様に利用することができます。

何故ここで一旦キャプチャしているかというのはこの後のForEachの中で何度も同じ演算を行うのが非効率的であるため、ForEachに入る前に先に演算を済ませておきます。

if (InputFlag)
{
  rot.Value = math.mul(rot.Value, quaternion.RotateY(10 * dt));
  translation.Value.z += 10 * dt;
}

ここも説明不要かと思われますが一応。

事前に演算しておいたInputFlagを参照し、Trueであれば実行します。

後は実行してみましょう!マウスをクリックしたり、スペースキーを押せば回転しながらZ奥に進むはずです!

以上で、入力受付に関しての説明を終わります。

まとめ

これでTinyUnityとECSの基礎に触れたことになります。

もし、ここまで触れてきて、「ちょっと合わないな…」と感じた方はしばらくTinyUnityから離れてもいいと思います。

0.20という数字があらわすように、まだまだ未完成なシステムです。

もうちょっと開発が進んでから触り始めても遅くはありません。

もっと触ってみたい!と感じた方はぜひ、公式サンプルであるTinyRacingを解析してみてみてください。

今回の記事で学んだことさえ理解できていれば、ある程度読むことができるでしょう。

以上で、TinyUnityのチュートリアルを終了します。

機会があればさらに踏み込んだTinyUnity、ECSの解説ができればと思います。

お疲れ様でした。

参考ページ

DOTS Runtime & Project Tiny: Getting Started [Public]

https://docs.google.com/document/d/1A8hen2hLFY5FLkC5gd3JP2Z-IpHfnAX-CpYLK3aOdwA/edit#heading=h.uqjyrv3tnvt8