PrefabからEntityを生成(Entity Component System)
ECS(Entity Component System) 基礎中の基礎で作成したCubeを大量に生成します。
Script
Cube
CubeDataで使用するデータを定義しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
using UnityEngine; using Unity.Entities; using Random = Unity.Mathematics.Random; namespace EmptyCan { public struct CubeData : IComponentData { public float Speed; public Vector3 Direction; public Vector3 Axis; public Quaternion Rotaiton; public Quaternion InitRotation; public float MaxRadius; public static CubeData Set(uint seed, float max_radius) { float min_speed = 100f; float max_speed = 10000f; Random random = new Random(seed); Quaternion rotation = Quaternion.Euler(random.NextFloat(0f, 360f), random.NextFloat(0f, 360f), random.NextFloat(0f, 360f)); float min_value = 1f / max_radius; float t = random.NextFloat(min_value, 1f); t = random.NextFloat(t, 1f); //原点付近で生成される数を減らすため float radius = t * max_radius; Vector3 direction = rotation * Vector3.up * radius; Vector3 axis = rotation * Vector3.forward; Quaternion init_rotation = Quaternion.FromToRotation(Quaternion.FromToRotation(Vector3.forward, axis) * Vector3.up, -direction); return new CubeData() { Speed = random.NextFloat(min_speed, max_speed), Direction = direction, Axis = axis, Rotaiton = rotation, InitRotation = init_rotation, MaxRadius = max_radius }; } } } |
Entityの取得及びComponentの追加を行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using Unity.Entities; using UnityEngine; using Unity.Mathematics; namespace EmptyCan { public class CubeAuthoring : MonoBehaviour { public uint Seed; public float MaxRadius; class Baker : Baker<CubeAuthoring> { public override void Bake(CubeAuthoring authoring) { CubeData data = CubeData.Set(math.max(1, authoring.Seed), math.max(1f, authoring.MaxRadius)); Entity entity = GetEntity(TransformUsageFlags.Dynamic); AddComponent(entity, data); } } } } |
Cubeを動かすための処理です。今回は大量にCubeを動かすのでJobSytemを使用して並列に実行しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using Unity.Burst; using Unity.Entities; using Unity.Transforms; using UnityEngine; namespace EmptyCan { public partial struct CubeSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { CubeUpdateJob job = new CubeUpdateJob() { Elapsed = (float)SystemAPI.Time.ElapsedTime }; job.ScheduleParallel(); } } [BurstCompile] partial struct CubeUpdateJob : IJobEntity { public float Elapsed; void Execute(in CubeData cube, ref LocalTransform xform) { float radius = cube.MaxRadius; float angle = cube.Speed / radius * Elapsed; Vector3 direction = cube.Direction; Vector3 axis = cube.Axis; Quaternion init_rotation = cube.InitRotation; Vector3 position = Quaternion.AngleAxis(angle, axis) * direction; xform.Position = position; Quaternion quaternion = init_rotation * Quaternion.FromToRotation(Vector3.forward, axis); quaternion = Quaternion.AngleAxis(angle, axis) * quaternion; xform.Rotation = quaternion; } } } |
Cubeの生成
Prefabを使用してCubeを生成します。以下のScriptはCubeを生成する際に使用するデータを定義しています。
1 2 3 4 5 6 7 8 9 10 11 |
using Unity.Entities; namespace EmptyCan { public struct Config : IComponentData { public Entity Prefab; public int SpawnCount; public uint RandomSeed; } } |
Cubeを生成するためのEntityの取得とComponentの追加を行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using Unity.Entities; using UnityEngine; using Unity.Mathematics; namespace EmptyCan { public class ConfigAuthoring : MonoBehaviour { public GameObject Prefab; public int SpawnCount; public uint RandomSeed; class Baker : Baker<ConfigAuthoring> { public override void Bake(ConfigAuthoring authoring) { Config data = new Config() { Prefab = GetEntity(authoring.Prefab, TransformUsageFlags.Dynamic), SpawnCount = authoring.SpawnCount, RandomSeed = math.max(1, authoring.RandomSeed) }; AddComponent(GetEntity(TransformUsageFlags.None), data); } } } } |
Cubeを生成するためのSystemです。
- RequireForUpdate
SubScene内に指定したComponentがないとSystemが起動しないようにできます。よって、このSystemはConfigが存在しない場合は実行されません。 - SystemAPI.GetSingleton
Componentを一つだけ取得できます。これを利用してConfigを取得します。 - state.EntityManager.Instantiate
指定した数だけPrefabからEntityを生成します。 - state.Enabled = false
Systemを無効にします。これにより、Systemが一度だけ実行されるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using Unity.Burst; using Unity.Collections; using Unity.Entities; using Random = Unity.Mathematics.Random; namespace EmptyCan { [UpdateInGroup(typeof(InitializationSystemGroup))] public partial struct SpawnSystem : ISystem { [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate<Config>(); //Configが存在しない場合、Systemは実行されない } [BurstCompile] public void OnUpdate(ref SystemState state) { Config config = SystemAPI.GetSingleton<Config>(); //SpawnCountだけEntityを取得 NativeArray<Entity> entities = state.EntityManager.Instantiate(config.Prefab, config.SpawnCount, Allocator.Temp); //取得したEntityのデータを設定 Random random = new Random(config.RandomSeed); foreach (Entity entity in entities) { RefRW<CubeData> cube = SystemAPI.GetComponentRW<CubeData>(entity); cube.ValueRW = CubeData.Set(random.NextUInt(), cube.ValueRO.MaxRadius); } state.Enabled = false; //Systemを止める } } } |
設定と実行結果
CubeAuthoringを追加したPrefabを作成します。
空のGameObjectを作成し、ConfigAuthoringを追加します。これをSubScene内へ移動します。今回はSpawnCount=5000、RandomSeed=10としました。
これを実行すると以下のように、回転するCubeが大量に生成されます。
参考ページ
-
前の記事
ECS(Entity Component System) 基礎中の基礎 2025.01.09
-
次の記事
記事がありません
コメントを書く