1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Unity DOTSでEntityを消したい

Last updated at Posted at 2022-12-28

本題の前に

ただの大学生がUnity DOTSを実際に触ってみる。2日目です。いつものように嘘が混じってるかもしれません。ごめんなさい。
昨日の記事は こちら

環境

Unity 2022.2.1f1
Entities 1.0.0-pre.15
Burst 1.7.4

今日の内容

生成したEntityを消したい。今日はその一心で頑張ってました。そして、ISystemとSystemBaseの差に気がつかされました。
昨日は内容が本当に内容だったので、今日は適当に書いたコードも載せます。

Entityを消す。

どうやら、2通り消し方があるっぽい。
1個目がEntityManager.DestroyEntity()を使う方法。
2個目がEntityCommandBuffer.DestroyEntity()を使う方法です。

何が違うのか

正直、良くわからんというのが本音。バッファーッテナンヤ
今わかってるふんわりとしたものを書きます。

EntityManager

1個目の方は上手く使うのは難しそうだったってこと。foreachで条件に合ったEntity全部消し飛ばすコードを書いたら、EntityManagerを過労死させるんじゃねぇって言われました。(意訳)
まぁ詳細に言えば非同期処理に対応していなくて連続して使用するとパンクしてしまうようです。

EntityCommandBuffer

2個目のほうは使うまでが遠い。あとISystemでは使えないっぽいですね。(最適化できないっぽい?)なぜかというと、ISystemstructでしか使えず、それではCommandBufferの取得の最初の段階である、BeginSimulationEntityCommandBufferSystemの取得が上手くいかなかったです。ただ、CommandBufferの取得方法は色々あるみたいなのでもう少し検証が必要かもしれません。

結局

EntityManagerは取得が簡単で、ISystemでもSystemBaseでも使えるようです。なので簡単な処理はEntityManager。複雑な処理はCommandBufferを引っ張り出してくる手法が良さそうです。

適当に書いたコード

昨日紹介した、Unity公式ドキュメント中に落ちているサンプルコードで色々遊んでいました。しばらくしたら、Cube消したいなーというコードです。

using Unity.Burst;
using Unity.Entities;
using UnityEngine;

[BurstCompile]
public partial class CubeSystem : SystemBase
{
    private BeginSimulationEntityCommandBufferSystem _entityCommandBufferSystem;

    protected override void OnCreate()
    {
        // EntityCommandBufferの取得
        _entityCommandBufferSystem = World.GetOrCreateSystemManaged<BeginSimulationEntityCommandBufferSystem>();
    }
    protected override void OnDestroy()
    {
        
    }

    [BurstCompile]
    protected override void OnUpdate()
    {
        int i = 0;
        var _ecb = _entityCommandBufferSystem.CreateCommandBuffer();
        foreach (var (_componentData, _entity) in SystemAPI.Query<RefRW<CubeData>>().WithEntityAccess())
        {
            _componentData.ValueRW._liveTime += 0.1f;
            if(_componentData.ValueRW._liveTime >= 1000f)
            {
                //CommandBufferでデストロイ!
                _ecb.DestroyEntity(_entity);
            }
            i++;
        }
        Debug.Log($"キューブの数は、{i}個です。");
    }
}

で、色々苦戦したことを上に書いたのですが、それ以上に知っておいて得だなと思ったコードがあるので、少し紹介します。
多くの人が知ってるかもしれないんですけど…

コード解説(そんな大そうなものではない)

ECSのforeach

Entity.ForEachという構文がどうにも好きになれない私は純粋なforeachで書いてみました。しかし、Componentは取得できてもEntityが取得できない!!!という現象に陥りました。結果以下のコードで良かった。

foreach (var (_componentData, _entity) in SystemAPI.Query<RefRW</*Componentの条件*/>>().WithEntityAccess())
{
    //処理
}

WithEntityAccess()が肝でした。そうすると、Entityも一緒に降ってくるようになって幸せになりました。
え?Entity.ForEachを使えば楽だって?それは分かってる。

情報更新

ネットのどこを漁ってもBeginSimulationEntityCommandBufferSystemの取得をするときはWorld.GetOrCreateSystem<BeginSimulationEntityCommandBufferSystem>()を使え!って書いてありました。
しかし、バージョンの更新の影響なのかそれではエラーになってました。なので、Worldのコードを漁るとそれっぽいメソッドを発見。
World.GetOrCreateSystemManaged<BeginSimulationEntityCommandBufferSystem>()でした。Managedね。よくわからんけどこれで動いたからよし!(後々理解したいの意)

おわり

昨日よりは内容あったんじゃないっすか?明日は、当たり判定とかInput Systemとの連携とかそこら辺をやりたい所存。
雑記にお付き合いいただきありがとうございました。また明日。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?