UnityでECSを使ってMRアプリを作ってみた
この記事はjig.jp Advent Calendar 2023の12月11日(月)の記事です。
今年はMeta Quest3が発売されましたね。UnityでのMRアプリ開発は、去年と比べて格段に開発しやすくなってきました。
また、Unity 2022 LTSではECS (Entity Component System)が正式サポートされました。
MRアプリでECSを使うことで、処理の高速化が狙えそうです。
では、Quest3向けのMRアプリを作っていきましょう。
Advent Calendarということで、たくさんのキャンディーを降らせるアプリを作ります。
作成するプロジェクトはGitHubのこちらのリポジトリに公開しています。
環境構築
Unity HubからNew Projectを選択します。Unity バージョンは2022LTSにします。
Unity Hubから 3D (URP)で新規プロジェクトを作成します。
必要なパッケージをインストールします。
Assets>Open C# Projectから、プロジェクトをエディタで開きましょう。
manifest.jsonに以下を追記します。
{
"dependencies": {
"com.meta.xr.sdk.core": "59.0.0",
"com.meta.xr.sdk.interaction": "59.0.0",
"com.unity.entities": "1.0.16",
"com.unity.entities.graphics": "1.0.16",
"com.unity.physics": "1.0.16",
}
}
MRのためのパッケージと、ECSのためのパッケージをまとめて追加しました。
UnityEditorを開くと、自動でパッケージがインストールされます。
ちなみに、メニューの表示はUnity Search機能が便利です。先ほどのメニュー表示や、これから多用するウィンドウ表示を検索して実行できます。
MR開発
プロジェクトの準備ができました。次にQuest3向けの開発をしましょう。
まずはビルド設定を変更します。
ビルド設定
File>Build Settingsを開き、以下の設定をします。
プラットフォームは、Androidを選択する
Texture Compressionは、ATSCを選択する
設定を変更したら、Switch Platformボタンを押して反映します。
Oculusの設定
他にもOculusの設定が必要です。
Oculusの設定は、自動で修正を適用できます。
Edit>Project Settingsウィンドウを開きます。
OculusタブからFix AllボタンとFix Applyボタンを押して、設定を適用します。
Checklistの内容がすべてVerified Itemsになれば完了です。
パススルー&ハンドトラッキング
続いて、パススルーとハンドトラッキングを有効にしましょう。
Oculus>Tools>Building Blocksウィンドウを開きます。
以下の3つのBlockをクリックして追加します。
Camera Rig
Passthrough
Hand Tracking
追加したCameraRigとMainCameraが競合するため、使用しないMainCameraを削除しておきましょう。
これでパルスルーとハンドトラッキングの設定は完了です。
URP用のマテリアル
ハンドのマテリアルを、URPで表示できるように更新しましょう。
ProjectウィンドウからAssets>Resourcesフォルダで右クリックし、Create>Materialを選択しましょう。
名前をHandMaterialとします。
これでマテリアルが準備できました。
ハンドトラッキングのマテリアルに適用しましょう。
HierarchyウィンドウからHand Trackingオブジェクトを選択します。
InspectorウィンドウからSkinned Mesh Rendererを選択し、作成したマテリアルに変更します。
これでURP用のマテリアルの設定が完了しました。
MRアプリを動かす
アプリを起動してみましょう。
Quest3で起動するため、PCとQuest3を接続します。
File>Build Settingsを開きます。
Run Deviceを接続したQuest3にして、Build And Runボタンを押します。
アプリを起動して、パススルーでハンドトラッキングできることを確認しましょう。
ECS開発
MRアプリの開発は完了です!
次に、ECSの開発をしましょう。
この記事では、ECSの紹介のために説明をかなり省略しました。ECSの説明はこちらの動画 はじめての Unity ECS - Entity Component System を使ってみよう!が分かりやすいです。
シーンの設定
まず、開いているSampleSceneの名前をMainに変更します。
そして、ECSのためのシーンを追加します。Hierarchyを右クリックしてNew Sub Scene>Empty Sceneを選択します。
シーンの名前を"Sub"にします。
Subシーンは、シーンに追加したGameObjectを、Unityが自動でECSのオブジェクトに変換してくれます。
シーンにキャンディーを生成するスポナーを追加しましょう。
Subシーンを右クリックして、GameObject>Create Emptyで追加します。空のGameObjectはSpawnerとしましょう。
Componentを実装
ここからはコードの実装です。Entityを持つComponentを実装します。
ECS(Entity Component System)のEとCですね。
実装する2つのファイルを作成しましょう。
Assets>ScriptsフォルダにConfigAuthoring.csとCandyAuthoring.csファイルを追加します。
名前をAuthoringとしているのは、ECSのComponentをMonoBehaviourからベイクするためです。
ConfigAuthoringの実装
ConfigAuthoring.csに次のコードを追記しましょう。
using Unity.Entities;
using UnityEngine;
public struct Config : IComponentData
{
public Entity Prefab;
public int SpawnRadius;
public int SpawnCount;
}
public class ConfigAuthoring : MonoBehaviour
{
public GameObject Prefab = null;
public int SpawnRadius = 10;
public int SpawnCount = 1000;
class Baker : Baker<ConfigAuthoring>
{
public override void Bake(ConfigAuthoring src)
{
var data = new Config()
{
Prefab = GetEntity(src.Prefab, TransformUsageFlags.Dynamic),
SpawnRadius = src.SpawnRadius,
SpawnCount = src.SpawnCount,
};
AddComponent(GetEntity(TransformUsageFlags.None), data);
}
}
}
ConfigストラクトがEntityを持つComponentです。
ConfigAuthoringクラスは、Unity EditorからGameObjectに貼り付けられるクラスです。このクラスには、Config Componentの生成方法を記述しています。
CandyAuthroingの実装
続いて、CandyAuthoring.csに次のコードを追記しましょう。
using Unity.Entities;
using UnityEngine;
struct Candy : IComponentData { public float Speed; }
class CandyAuthoring : MonoBehaviour
{
public float Speed = 3f;
class Baker : Baker<CandyAuthoring>
{
public override void Bake(CandyAuthoring src)
{
var data = new Candy { Speed = src.Speed };
AddComponent(GetEntity(TransformUsageFlags.Dynamic), data);
}
}
}
キャンディーそれぞれにSpeed情報を持たせています。
Systemを実装
Systemには、Componentに対する動作を実装します。
Componentと同様に、Assets>ScriptsフォルダにCandySpawnSystem.csとCandySystem.csファイルを追加します。
CandySpawnSystemの実装
CandySpawnSystem.csに次のコードを追記しましょう。
このSystemはConfigに対応します。
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct CandySpawnSystem : ISystem
{
public void OnCreate(ref SystemState state)
=> state.RequireForUpdate<Config>();
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var config = SystemAPI.GetSingleton<Config>();
var instances = state.EntityManager.Instantiate
(config.Prefab, config.SpawnCount, Allocator.Temp);
var rand = new Random(100);
foreach (var entity in instances)
{
var xform = SystemAPI.GetComponentRW<LocalTransform>(entity);
var v = rand.NextFloat3(-1, 1);
var size = rand.NextFloat(.3f, .5f);
xform.ValueRW = LocalTransform
.FromPosition(math.float3(v.x, v.y, v.z) * config.SpawnRadius)
.WithScale(size);
}
state.Enabled = false;
}
}
CandySpawnSystemはConfigクラスがあるComponentに対して自動で適用されます。このSystemは、ランダムな位置にキャンディーを生成しています。
CandySystemの実装
CandySystem.csに次のコードを追記しましょう。
using Unity.Burst;
using Unity.Entities;
using Unity.Transforms;
public partial struct CandySystem : ISystem
{
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var job = new CandyUpdateJob() { DeltaTime = SystemAPI.Time.DeltaTime };
job.ScheduleParallel();
}
}
partial struct CandyUpdateJob : IJobEntity
{
public float DeltaTime;
void Execute(in Candy candy, ref LocalTransform xform)
{
xform.Position.y -= DeltaTime * candy.Speed;
if (xform.Position.y < -10f) xform.Position.y = 10f;
}
}
このCandySystemは、キャンディーを上から下に動かす処理をしています。
キャンディーを用意
Systemで生成し、動かすキャンディーを用意しましょう。
Subシーンを右クリックして、GameObject>3D Object>Sphereを選択しGameObjectを作成します。名前はCandyとします。
キャンディーマテリアルの作成
Assets>Create>Materialを選択しマテリアルを作成します。
マテリアルの色を変更しましょう。
SurfaceInputs>Base Mapから色を設定します。色はキャンディーらしく0x19FF71としました。
次にCandyオブジェクトを選択し、Mesh RendererのMaterialsに作成したマテリアルを適用します。
CandyAuthroingの適用
Candyオブジェクトを選択し、Add ComponentからCandyAuthoringを追加します。
キャンディーのPrefab化
作成したCandyオブジェクトは、Projectウィンドウにドラッグ&ドロップしてPrefabに変換します。
Candyスポナーを設定
Subシーンに追加したSpawnerオブジェクトを設定しましょう。
Spawnerオブジェクトに、Add ComponentからConfig Authoringを追加します。
Config AuthoringのPrefabは、生成したキャンディーPrefabを設定します。
これで設定完了です!
ECSを動かす
MRアプリを起動した手順と同様にアプリを動かしてみましょう。
File>Build Settingsを開き、Build And Runボタンを押します。
動いていますね!
まとめ
Unityでキャンディーを降らせるアプリを作ってみました。
MeshAPIで壁に当たり判定をつけたり、ハンドトラッキングに当たり判定をつけても面白そうですね!
この記事が気に入ったらサポートをしてみませんか?