現在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の数が増えたときにチャンク構造のうんたらかんたらでエラーが出ないとも限らないので出たら修正します。