いんでぃーづ

ゲームいろいろ、いろいろ自由

Unity ECS : Jobで攻撃の総当たり判定を行うときのテンプレっぽいもの

現在ECSでRTS(タワーディフェンス)を作っているのですが、攻撃の当たり判定と敵の当たり判定を総当たりで判定するのにちょっと手間取ったのでメモ。

当たり判定を総当たりでチェックしたい場合、一方をクエリにとるジョブに対してもう一方のNativeArrayをジョブに持たせるという方法しかないのかなあと思います。

※コードは元コードから抜粋して名前変えてあるのでコンパイル通らないかもしれません

まず攻撃のあたり判定となるComponentDataを定義

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;

[System.Serializable]
public struct AttackData : IComponentData {
    public int AttackPower;  // 攻撃力
    public float HitCollisionRadius;  // 攻撃の当たり判定の半径
}

次に攻撃が当たるユニットとなるComponentData

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;

[System.Serializable]
public struct UnitData : IComponentData
{
    public int HP;
}

今回はUnitDataをクエリにとるジョブに対し、攻撃判定の配列を持たせます。

以下が当たり判定の総当たりを行うSystemです。

public class AttackJudgeSystem : JobComponentSystem
{
    EntityQuery AttackQuery;

    protected override void OnCreate()
    {
        base.OnCreate();

        AttackQuery = GetEntityQuery(typeof(AttackData), typeof(Translation));
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        
        inputDeps = new AttackJudgeJob() {
            AttackHitDataArray = AttackQuery.ToComponentDataArray<AttackData>(Allocator.TempJob),
            AttackHitTranslationArray = AttackQuery.ToComponentDataArray<Translation>(Allocator.TempJob)
        }.Schedule(this, inputDeps);

        return inputDeps;
    }

    [BurstCompile]
    struct AttackJudgeJob : IJobForEachWithEntity<UnitData, Translation>
    {
        [ReadOnly, DeallocateOnJobCompletion] public NativeArray<AttackData> AttackHitDataArray;
        [ReadOnly, DeallocateOnJobCompletion] public NativeArray<Translation> AttackHitTranslationArray;

        public void Execute(Entity entity, int index, ref UnitData unitData, ref Translation translation)
        {
            for (int i = 0; i < AttackHitDataArray.Length; i++) {
                if (Vector3.Distance(AttackHitTranslationArray[i].Value, translation.Value) < AttackHitDataArray[i].HitCollisionRadius) {
                     // 当たり判定が一定以内にあるので当たった
                }
            }
        }
    }
}

DeallocateOnJobCompletion 入れないと

A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.

と言われる。


渡す配列がReadOnlyの場合はこれでいけるけど、データを書き換えたいときは CommandBuffer を使えばいけそう。

いまのとここれでいけてるけどEntityの数が増えたときにチャンク構造のうんたらかんたらでエラーが出ないとも限らないので出たら修正します。


“Unity” and Unity logos are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere, and are used under license.


免責事項

当サイトの広告バナー、リンクによって提供される情報、サービス内容について、当サイトは一切の責任を負いません。

また、当サイトの情報を元にユーザ様が不利益を被った場合にも、当サイトは一切の責任を負いません。

すべて自己責任でお願いします。