【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クラスを書き換えます
MeshInstanceRendererComponent など設定して実行すると
今まで通り描画されますが、回転しないよね。
回転スクリプト( Move.cs ) を変更する
gist.github.com
変更点は ※ を参照してください。
あとは Entity の Archetype に Move を追加するだけ
var archetype = manager.CreateArchetype(new ComponentType[] { typeof(Position), typeof(Rotation), typeof(Move), // ※ 追加する });
動きました!!
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も無効に!
【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と関係ないので実装詳細は飛ばしても問題なし!
Hybrid ECS化
プレハブを選択し Add Component から "Game Object Entity" をアタッチする。
あとは Move.cs を修正する
ECS にしたが、実行してもあまり差が感じないよね。
原因は更新部分がまだマルチスレッドしていません。
最低限のマルチスレッド処理ができました
Unity 従来の使い方でマルチスレッド化できたので
Hybrid ECSはとても手軽で魅力的ですね。
【Unity】テキストの「均等割り付け」と「両端揃え」
UI作成時、このような表現はたまにほしくなるよね。
IMeshModifierを実装することで実現できます。
gist.github.com
【Unity】ボタン作成時のカスタム拡張
UnityEditor のメニューに [GameObject/UI/Button] でボタンを作成したが、
プロジェクトによってはカスタムのコンポーネントを追加したり、
デフォ画像を設定したりしたいわけですが、
毎回手動でやると面倒ですよね!!!!
UnityEditor.UI.MenuOptions というクラスをHACKしてコールバックを追加してみました。
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)