Unity DOTS 入門 (1) - 従来のUnityの設計をDOTSの設計に変換
DOTSのチュートリアルとして、立方体を回転させる簡単なプログラムを作って、従来のUnityの設計をDOTSの設計に変換します。
・Unity 2019.3.14.f1
・Entities 0.11.1
1. 従来のUnityの設計 と DOTSの設計
DOTSの中核である「ECS」では、ID(エンティティ)、データ(コンポーネント)、動作(システム)を分離します。
・エンティティ : ID
・コンポーネント : データ
・システム : 動作
今回のチュートリアルは、「GameObject + MonoBehaviour」を「エンティティ + コンポーネント + システム」に変換する作業になります。
2. DOTSパッケージのインストール
DOTS パッケージのインストール手順は、次のとおりです。
(1) メニュー「Window → Package Manager」でPackage Managerを開く。
(2) ウィンドウ上部の「Advances → show preview packages」をチェック。
(3) 「Hybrid Renderer」(0.5.2)を検索してインストール。
これによって、「Entities」が依存関係として追加され、依存する関連パッケージ(Burst、Collections、Jobs、Mathematicsなど)が再帰的に追加されます。
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度回転)。
(5) 実行。
4. 従来のUnityの設計からDOTSの設計への変換
次に、従来のUnityの設計をDOTSの設計に変換します。
(1) Cubeに「ConvertToEntity」コンポーネントを追加。
これによって、シーン起動時に「GameObject」が「エンティティ」に変換されます。
「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ウィンドウでデータ編集できるようになります。
(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ウィンドウからは消えます。
メニュー「Window → Analysis → Entity Debugger」で「Cube」の存在を確認できます。