0
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?

ECS 記述方法に関する備忘録

Last updated at Posted at 2024-06-09

1. Schedule と .ScheduleParallelの違いについて

どうやら、
Schedule = ワーカースレッド上のシングルスレッド
ScheduleParallel = ワーカースレッド上のマルチスレッド
といった違いがあるようですが、具体的にコード記述していく上でどんな風に違いが出てくるのか、備忘録を残します。(随時追加予定)

GetSingletonEntityが利用できない

ScheduleParallelでSystemAPI.GetSingletonEntityを使おうとすると、以下のようなエラーが出ます。
(ECSのエラー長すぎ...)

InvalidOperationException: AttackEnemyJob.JobData.LocalTransformLookup is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
Unity.Jobs.LowLevel.Unsafe.JobsUtility.ScheduleParallelFor (Unity.Jobs.LowLevel.Unsafe.JobsUtility+JobScheduleParameters& parameters, System.Int32 .....

ReadOnlyしか使えない

例えば、
[ReadOnly] public ComponentLookup LocalTransformLookup;
のように記述する必要があります。
その際に、
using Unity.Collections;
を使うことを忘れないように。

ecbについては、
ecb = state.World.GetOrCreateSystemManaged().CreateCommandBuffer().AsParallelWriter(),
public EntityCommandBuffer.ParallelWriter ecb
のように記述できる。

あと、
public void Execute(Entity entity, CharactorTargetEntity targetEntity, CharactorAttackProperties attackProperties, [ChunkIndexInQuery] int sortKey)
var newAttackPrefab = ecb.Instantiate(sortKey, AttackPrefab);
のように、sortkey関係の記述も忘れずに。

動作が重くなりそうなところは、積極的にParallelを使っていきましょう。

2. foreachとExcuteの使い分け

基本的には、Unity公式もECSではExcute利用を推奨しているので、Excuteを使いたいと思いますが、foreachでないと記述できないケースもあるので、使い分けについてメモを残します。

foreachを使う必要がある例

SystemAPIを使いたい

Excute内では、JOB化して高速計算するための制約として、SystemAPI.GetComponentとかは使えません。
ただ、

MobaTeamLookup = SystemAPI.GetComponentLookup<MobTeam>(true),
[ReadOnly] public ComponentLookup<MobTeam> MobaTeamLookup;

のように記述すれば、実質利用できるので、ちょっと記述は面倒ですがExcuteを使った方がよいと思います。

ゲームオブジェクトを呼び出したい

例えば以下のような記述を使って、MonoBehaviorを呼び出し、ゲームオブジェクトを出現させたい場合、
Excuteは利用できないので、foreachを使う必要があります。

public Action<int, float3> OnDealDamage;
OnDealDamage?.Invoke(damageToCharactor.Value, transform.Position);

entityは制約が多いので、ゲームオブジェクトを出現させたい、というケースは結構多いのではないかと思います。
例えば私の場合は、entityがダメージを受けた時にダメージアイコン(「-10」とか)を出したいですが、entityで利用できるテキストデザインに厳しい制約があるようで、ゲームオブジェクト使いました。

特定EntityのCompornentを呼び出す際の記述方法

微妙な記述方法の違いが中々覚えられないので、纏めます。

foreachの場合

特定Entityのコンポーネントやその中身を参照

SystemAPI.GetComponent<コンポーネント名>(entity名)

コンポーネント追加

ecb.AddComponent(entity名, new コンポーネント名 { });

※foreach完了後、OnUpdate内での以下記述を忘れずに。

ecb.Playback(EntityManager);
ecb.Dispose();

Excuteの場合

特定Entityのコンポーネント(またはコンポーネント内の数値)

コンポーネント名Lookup = SystemAPI.GetComponentLookup<コンポーネント名>(),
[ReadOnly] public ComponentLookup<コンポーネント名> コンポーネント名Lookup;
コンポーネント名Lookup[entity名].コンポーネント内の数値名(Valueなど)

Excute内で定義したコンポーネントを使って、Excute実行中Entityのコンポーネントにアクセス

Execute(Entity entity, LocalTransform transform)
transform.Position

Excute実行中以外のEntityのコンポーネントにアクセスする場合には、コンポーネント名Lookupの利用が必須。
厄介なのは、Excute内で定義済みのコンポーネントを、CompornentLookUpで呼び出すと
InvalidOperationException: The writeable ComponentTypeHandle ShortDistanceAttackEnemyJob.JobData.__TypeHandle.__Unity_Transforms_LocalTransform_RW_ComponentTypeHandle is the same ComponentLookup as ShortDistanceAttackEnemyJob.JobData.LocalTransformLookup, two containers may not be the same (aliasing).
のように、大量のエラーが出現する。
併用はできないことに注意する。

0
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
0
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?