【Unity】Hybrid ECS から Pure ECS へ

前回 でMeshInstanceRendererを使って描画できました。
PositionComponent とか RotationComponent とかも使ってPure ECS を少し理解が深まったので、
GameObject.Instantiate(...) でオブジェクトを生成ではなく、
Pure ECSらしく書き換えを行いたいです。

まずは調査!!

var manager = World.Active.GetOrCreateManager<EntityManager>();
var archetype = manager.CreateArchetype(...); // Position とか Rotationとか
var entity = manager.CreateEntity(archetype);
var look = ... // MeshInstanceRenderer
manager.AddSharedComponentData(entity, look);

以上の意味は自分なりに解釈すると、

EntityManager に Archetype を指定し Entity を生成し、
MeshInstanceRenderer を Entity に追加する
これで MeshInstanceRenderer は Entity の情報 ( Position , Rotationなど )で描画してくれる
あとは やりたいことを ComponentSystem とか JobComponentSystem を使って更新する

かなぁ~(間違ったらコメントで指摘していただければと・・・

オブジェクトの生成部分を変更する

オブジェクトは GameObject.Instantiate(...) ではなく
EntityManager から生成するため、Managerクラスを書き換えます

gist.github.com

MeshInstanceRendererComponent など設定して実行すると
f:id:kou_yeung:20181109142013g:plain

今まで通り描画されますが、回転しないよね。

回転スクリプト( Move.cs ) を変更する

gist.github.com
変更点は ※ を参照してください。

あとは Entity の Archetype に Move を追加するだけ

var archetype = manager.CreateArchetype(new ComponentType[]
{
    typeof(Position),
    typeof(Rotation),
    typeof(Move),      // ※ 追加する
});

f:id:kou_yeung:20181109143408g:plain
動きました!!
200FPS 以上になりました。

もう一歩先へ

Archetype はハードコーディングなのが不満です!!
どう解決するかなぁと思い、「そうだ、ComponentDataWrapper があるじゃないか!」

やりたいこと、
Prefab に アタッチしてる ComponentDataWrapper<T> の T 型を取得すればいいじゃない?(w)

書いた。
gist.github.com

GameObjectにアタッチした ComponentDataWrapperBase のコンポーネントを取得し
そのコンポーネントの基底クラスのジェネリック型パラメーターを取得する。

それと、MeshInstanceRendererComponent など SharedComponent が存在するかもしれないので
IsSharedComponent == true のものは取り除けばいいです

ついでに、CreateMeshInstanceRenderer() メソッドも提供し
MeshFilter や MeshRenderer から動的MeshInstanceRendererを生成すればスッキリです。

あとは、Manager のオブジェクト生成部分を書き換えればいい
gist.github.com

プログラム変更なしで、Archetype の調整ができました!!

まぁ

まだ検証段階なので、
Prefab から Archetype を取得するのが本当にいいのかも疑問ですが。。
結果的に ECS が理解を深まったからいいや~

【Unity】Hybrid ECS + MeshInstanceRenderer

前回でHybrid ECSを使ってUpdate() 部分をマルチスレッド化してみた。

やはり描画負荷が高いよね。
MeshInstanceRenderer を使いたくなる!!
調べても使い方が難しく意味が分からん!(じゃぁこの投稿は何だよw

MeshInstanceRenderer

試しにGameObject アタッチしメッシュやマテリアルを設定しても描画してくれないよね。
理由はTransformの情報がない(?)かと思います。

じゃ、ネットでMeshInstanceRendererについて調べたら、

var manager = World.Active.GetOrCreateManager<EntityManager>();
var archetype = manager.CreateArchetype(...); // Position とか Rotationとか
var entity = manager.CreateEntity(archetype);
var look = ... // MeshInstanceRenderer
manager.AddSharedComponentData(entity, look);

と、今まで使って来なかった書き方をヒットします。

やりたいこと

従来の概念をあまり捨てないでどうやってMeshInstanceRendererを使うか?
(ECSの考えにあってるかどうかわからんが) 書きました。
gist.github.com

上記のコンポーネントをGameObjectにアタッチすると、

PositionComponent
RotationComponent
MeshInstanceRendererComponent
CopyTransformFromGameObjectComponent

を勝手にアタッチしてくれます。
なぜか ScaleComponent の情報がコピーしてくれないので、今回は無視する!

Awake() 時に、
MeshFilter と MeshRenderer があれば
情報を取得し MeshInstanceRenderer にセットする
ついでにMeshRendererも無効に!

実行結果

f:id:kou_yeung:20181108165006g:plain
160FPS 以上になりました。
これぞ Hybrid ECS!!

次回:
【Unity】Hybrid ECS から Pure ECS へ - 浮遊島

【Unity】Hybrid ECS

Entity Component Systemを使いたいが、Pure ECSの学習コストが高い!
大量なオブジェクトのUpdate()だけスレッドで処理したく、
Hybrid ECSを試しました。( Unity バージョン:2018.2.10f1 )

準備

Scripting Runtime Version 設定

ECS を使うために、.NET4.x に設定する必要があります

Package をインストール

Unityエディタで [Window] -> [Package Manager] を開き [All] タブを選択し
以下Package をインストールする

・Entities (0.0.12-previre.19)

オブジェクトを大量生成する

プレハブを指定して大量なオブジェクトを生成するクラスです。
生成したら座標や向きを設定する
※ECSと関係ないので実装詳細は飛ばしても問題なし!

gist.github.com

動かせるスクリプトを作成する

今までのやり方でオブジェクトを動かせます
gist.github.com

f:id:kou_yeung:20181107165600g:plain
3xFPS ぐらい

Hybrid ECS化

プレハブを選択し Add Component から "Game Object Entity" をアタッチする。
あとは Move.cs を修正する

gist.github.com

ECS にしたが、実行してもあまり差が感じないよね。
原因は更新部分がまだマルチスレッドしていません。

Job で マルチスレッド

IJobParallelForTransformを実装し並列処理を行う。
gist.github.com

f:id:kou_yeung:20181107165316g:plain
5xFPS ぐらいになりました。

最低限のマルチスレッド処理ができました

Unity 従来の使い方でマルチスレッド化できたので
Hybrid ECSはとても手軽で魅力的ですね。

次回:
【Unity】Hybrid ECS + MeshInstanceRenderer - 浮遊島

【Unity】ボタン作成時のカスタム拡張

UnityEditor のメニューに [GameObject/UI/Button] でボタンを作成したが、
プロジェクトによってはカスタムのコンポーネントを追加したり、
デフォ画像を設定したりしたいわけですが、

毎回手動でやると面倒ですよね!!!!

UnityEditor.UI.MenuOptions というクラスをHACKしてコールバックを追加してみました。

gist.github.com

使い方

例: 自前の ButtonSE というコンポーネントを追加したい!
gist.github.com

とても手軽になりました!

MenuItem 重複による警告

Cannot add menu item 'GameObject/UI/Button' for method 'MenuOptions.AddButton' because a menu item with the same name already exists.

上記の警告が表示されるので、気になる場合

// MenuOptions.cs
[MenuItem("GameObject/UI/Button", false, 2001)]
↓
[MenuItem("GameObject/UI/Button/Create", false, 2001)]

に変更すれば警告は消えます。(その代わりにメニューの階層が深くなりますorz)