どうも、土鍋です。
ECSでEntityは取得できてもコンポーネントにどうやったらアクセスできるんだ?
という問題に直面した際にComponentLookupが使えます。
自分はこれを知らなくて苦労しました。
まずはコードをご覧ください。
public partial struct CitizenMoveSystem : ISystem { private EntityQuery _buildingQuery; [BurstCompile] public void OnCreate(ref SystemState state) { _buildingQuery = state.GetEntityQuery(typeof(LocalTransform), typeof(BuildingBase)); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Jobの発行処理 var job = new CitizenMoveUpdateJob() { Elapsed = (float)SystemAPI.Time.ElapsedTime, BuildingEntities = _buildingQuery.ToEntityArray(Allocator.TempJob), BuildingLookup = SystemAPI.GetComponentLookup<BuildingBase>(), BuildingPosLookup = SystemAPI.GetComponentLookup<LocalToWorld>() }; // 初期化 job.ScheduleParallel(); // Jobの予約 } }
partial struct CitizenMoveUpdateJob : IJobEntity { ~一部省略~ public NativeArray<Entity> BuildingEntities; [ReadOnly] public ComponentLookup<BuildingBase> BuildingLookup; [ReadOnly] public ComponentLookup<LocalToWorld> BuildingPosLookup; void Execute(ref CitizenBase citizen, ref LocalTransform transform) { ~一部省略~ foreach (var buildingEntity in BuildingEntities) { if (BuildingLookup[buildingEntity].buildingType == BuildingType.Food) { float distanceSq = math.distancesq(BuildingPosLookup[buildingEntity].Position, transform.Position); if (distanceSq < minDistanceSq) { minDistanceSq = distanceSq; closestBuildingPosition = BuildingPosLookup[buildingEntity].Position; } } } ~一部省略~
このコードではCitizenがBuildingEntitiyを全取得し、buildingTypeがFoodのものを選択し、一番近いものに訪問するということをやっています。
ComponentLookupについて
使い方
BuildingLookup[buildingEntity]
のようにEntityをIDとして配列の添え字のように記述することで、そのEntityのコンポーネントを取得することができます。
また、
BuildingLookup.HasComponent(buildingEntity)
のようにそのコンポーネントを持つかどうかのboolの取得もこのようにできます。
取得方法
SystemAPI.GetComponentLookup<BuildingBase>()
SystemAPI.GetComponentLookup<>()を使用することでほしいコンポーネントのComponentLookupを取得できます。
ちなみにEntityの取得はEntityQueryからToEntityArrayでNativeArray