写経:WAYN Games (DOTS 基礎編)
はじめに
この記事は以下の動画を写経したものです。
DOTS101-DOTS111 シンプルなTowerDeffenceのモックをDOTSで構築する方法を学びます。
できたもの
- 基本的な構造の理解
- Object を いくつかPointに沿って移動させる
- Object に モーション付き 3D モデルを使用する
- Entity の InstantiateとDestroy
- 基本的な Collision 判定
各動画
DOTS101
https://www.youtube.com/watch?v=N-xoBFi2YF0
この動画では、DOTSのInstallとWindowの説明です。ごくごく基本的な解説でCodeは作成しません。
※後に version up して、これらの手順や install するpackageは1部変更されます。
DOTS102
https://www.youtube.com/watch?v=FXgVuewJ_qU
この動画では SystemBase が解説されます。 既存のUnityでは、ScriptはなんらかのGameObjectにAttachしなければ動作しませんでしたが、これらのClassはただ書くだけで実行されます。 感の良い人はこの動画の時点でデータ指向はそういうことかとわかると思います。 BOX Objectを2つ表示してそれぞれ違うSpeedで移動させています。
DOTS103
https://www.youtube.com/watch?v=uXvuFMlBI3Y
この動画では、DynamicBuffer が解説されます。 複数のPointを配置されたGameObjetから取得し順番に移動させます。
DOTS104
https://www.youtube.com/watch?v=iDPfH0cCPuY
Version up された entities の install方法と ISystemが解説されます。 既存の code の修正方法などの説明があります。 この動画中のソースに TransformAspect が使用されている部分がありますが、 entities ver1.0.0 pre 63 で remove されます。最新版では代わりににLocalTransformを使用します。
- TransfomrAspect -> LocalTransform
※TransformAspectのmethodを使用している場合は、それぞれの方法で実装が必要です。
※ここでめでたいことに entitiesが’1.0.0に大幅 Version up され、正式リリースとなります。
DOTS105
https://www.youtube.com/watch?v=nXcLOnRGG0w&t=203s
この動画では、Baker が解説されます
Authoring -> Baking - > Runtime の図はとてもわかりやすいので必見です 4:00 くらいから始まります。
DOTS106
https://www.youtube.com/watch?v=uIfdINDCstQ
この動画では ISystem が解説されます。
DOTS107
https://www.youtube.com/watch?v=_35CzCxPqTg
この動画では IAspect が解説されます。
DOTS108
https://www.youtube.com/watch?v=n2NvbNtzkCE
この動画では Entity を Instantiateする方法などが解説されます。 Fee Asset モーション付き 3D model を表示させる方法などが解説されます。 この動画からぐっと見栄えが派手になります。 メモ:URPじゃないアセットのMaterialをURPように変換するコマンド
Edit > Rendering > Materials > Convert Selected build-in Materials to URP
DOTS109
https://www.youtube.com/watch?v=vs6h4waQpPA
DOTS上でモーション付きモデルを表示させる方法について解説されます。 EntitiyのInstatiateとDestroyまでの流れも解説され、ようやくゲームっぽい感じになってきます。 以下のようなQueryを使うことによって、オブジェクトを横断して共通なComponentを取得することなどがコードから理解出来るようになります。
foreach (var entity in SystemAPI.Query<Speed>() { // do something }
DOTS110
https://www.youtube.com/watch?v=YzezqDqr7RM
MouseでClickした箇所にTowerを配置する方法が解説されます。
DOTS111
https://www.youtube.com/watch?v=YzezqDqr7RM
Towerから弾を発射し、EnemyにHitしたらEnemyのHelthを減少させ、Healthが0以下になったら削除する。 といった一連の流れが解説されます。 この動画から動画中のソースと実行画面の不整合が発生しはじめ写経ポイントです!
- PhysicsCategory Assetsが突然現れる
Create -> Unity Physics -> Physics category name で作成可能です。
- 弾が配置されない!
以下のように修正する必要があります。 ProjectileSystem.cs
ecbBOS.SetComponent(e, new Translation() { Value = towerPosition });
vvv
ecbBOS.SetComponent(e, new LocalTransform { Position = towerPosition, Rotation = quaternion.identity, Scale = 1 });
こちらも先述したTransfomrAspect の removeの影響です
- 敵にあたらない弾が消えない 動画中だと消えているように見えるのですが、おそらく次の動画で説明するソースにCodeが記述されているようです。 この動画までの記事にしたいので自前で実装します。
Target.cs
public struct Target : IComponentData { public Entity Value; public float timeLife; // << 追加 }
ProjectileSystem.cs
.... ecbBOS.AddComponent(e, new Target() { Value = closestHitCollector.ClosestHit.Entity}); .... foreach(var (speed,target,transform,entity ) in SystemAPI.Query<RefRO<Speed>, RefRO<Target>, RefRW<LocalTransform>>().WithEntityAccess()) { //Debug.Log($"HasComponent:{positionLookup.HasComponent(target.ValueRO.Value)},{target.ValueRO.timeLife},{Time.time}"); if(positionLookup.HasComponent(target.ValueRO.Value) ) { ....
vvv
.... ecbBOS.AddComponent(e, new Target() { Value = closestHitCollector.ClosestHit.Entity, timeLife = Time.time+ 3.0f }); .... foreach(var (speed,target,transform,entity ) in SystemAPI.Query<RefRO<Speed>, RefRO<Target>, RefRW<LocalTransform>> ().WithEntityAccess()) { //Debug.Log($"HasComponent:{positionLookup.HasComponent(target.ValueRO.Value)},{target.ValueRO.timeLife},{Time.time}"); if(positionLookup.HasComponent(target.ValueRO.Value) && target.ValueRO.timeLife > Time.time) { ....
最後に
各動画のソースは branch に分かれて公開されているので、どうしても動かないという方は各 package の version を揃えてそちらも参考にしてみると良いと思います。素晴らしいですね。
https://github.com/WAYN-Games/DOTS-Training/tree/main
これはもう別Engineなんじゃない?というくらい書き方変わりますが、プログラマ的にはごりごりに最適化出来そうなので ボクハエガカケナイ という方は全力でいくのもアリなんじゃないでしょうか。 STGを書くのが楽しそうです。Collider周りも大きく変更されているので、それはまた別の記事で。
Thanks ! WAYN Games