見出し画像

Unity DOTS 入門 (1) - 従来のUnityの設計をDOTSの設計に変換

DOTSのチュートリアルとして、立方体を回転させる簡単なプログラムを作って、従来のUnityの設計をDOTSの設計に変換します。

・Unity 2019.3.14.f1
・Entities 0.11.1

1. 従来のUnityの設計 と DOTSの設計

DOTSの中核である「ECS」では、ID(エンティティ)、データ(コンポーネント)、動作(システム)を分離します。

エンティティ : ID
コンポーネント : データ
システム : 動作

画像6

今回のチュートリアルは、「GameObject + MonoBehaviour」を「エンティティ + コンポーネント + システム」に変換する作業になります。

2. DOTSパッケージのインストール

DOTS パッケージのインストール手順は、次のとおりです。

(1) メニュー「Window → Package Manager」でPackage Managerを開く。
(2) ウィンドウ上部の「Advances → show preview packages」をチェック。
(3) 「Hybrid Renderer」(0.5.2)を検索してインストール。

これによって、「Entities」が依存関係として追加され、依存する関連パッケージ(BurstCollectionsJobsMathematicsなど)が再帰的に追加されます。

3. 従来のUityの設計での実装

はじめに従来のUnityの設計で、立方体を回転させるプログラムを作成します。

(1) Unityでプロジェクトを作成。
(2) Hierarchyウィンドウの「+ → 3D Object → Cube」で立方体を追加。
(3) Cubeにスクリプト「Rotator」を追加し、以下のように編集。

using UnityEngine;

public class Rotator : MonoBehaviour
{
    public float speed;

    void Update()
    {
        transform.Rotate(0f, speed * Time.deltaTime, 0f);
    }
}

(4) Inspectorウィンドウで「Rotator」の「Speed」に180を指定(1秒間に180度回転)。

画像2

(5) 実行。

画像3

4. 従来のUnityの設計からDOTSの設計への変換

次に、従来のUnityの設計をDOTSの設計に変換します。

(1) Cubeに「ConvertToEntity」コンポーネントを追加。
これによって、シーン起動時に「GameObject」が「エンティティ」に変換されます。

画像4

Conversion Mode」の設定項目は、次のとおりです。

・Convert And Destroy : エンティティ変換後にGameObjectを破棄。
・Convert And Inject Game Object : エンティティ変換後にGameObjectを残す。

(2) スクリプト「Rotator」を次のように編集。
コンポーネント」を実装します。

using Unity.Entities;

[GenerateAuthoringComponent]
public struct Rotator : IComponentData
{
    public float speed;
}

コンポーネント」は「IComponentData」を継承した構造体(struct)で、データのみ定義します。[GenerateAuthoringComponent] はInspectorウィンドウでデータ編集できるようになります。

画像7

(3) Projectウィンドウにスクリプト「RotatorSystem」を追加し、以下のように編集。
システム」を実装します。

using UnityEngine;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using System;

public class RotatorSystem : SystemBase
{
    protected override void OnUpdate()
    {
        float deltaTime = Time.DeltaTime;

        Entities
            .ForEach((ref Rotation rotation, in Rotator rotator) =>
            {
                rotation.Value = math.mul(
                    math.normalize(rotation.Value),
                    quaternion.Euler(0f, math.radians(rotator.speed * deltaTime), 0f));
            })
           .ScheduleParallel();
   }
}

システム」は「SystemBase」を継承したクラスで、OnUpdate()をオーバライドして、フレーム毎の処理を記述します。「システム」は、シーン起動時に実行されます。

Entities.ForEach()で「Rotation」コンポーネントと「Rotator」コンポーネントを持つEntityを検索し、ラムダ関数(ForEachに引数として渡している関数)を実行します。ラムダ関数の引数は、読み書きするものは「ref」、読み込み専用のものは「in」を指定します。

ラムダ関数を実行するメソッドは、次の3種類があります。

・Run() : メインスレッドで即実行。
・Schedule() : 1つのスレッドでスケジュール実行。
・ScheduleParallel() : 複数のスレッドで並列にスケジュール実行。

今回は、ScheduleParallel()で実行しています。

(3) 実行。
従来のUnityの設計と同様に、立方体が回転します。

「Cube」は、シーン起動時にEntityに変換されるため、Hierarchyウィンドウからは消えます。

画像5

メニュー「Window → Analysis → Entity Debugger」で「Cube」の存在を確認できます。

画像4


この記事が気に入ったらサポートをしてみませんか?