https://aostols.tistory.com/46
여기서 이어서 진행됩니다.
소스에서 사용된 내용 몇개를 추가해 줍니다.
랜덤으로 스폰되어야 하기 떄문에 Random 관련 함수들을 추가해 줍니다.
using Unity.Mathematics;
public static class MathExtensions
{
public static float3 NextOnDisk(this ref Random self)
{
while (true)
{
var v = self.NextFloat2(-1, 1);
if (math.length(v) <= 1) return math.float3(v.x, 0, v.y);
}
}
public static quaternion NextYRotation(this ref Random self)
=> quaternion.RotateY(self.NextFloat(math.PI * 2));
}
MathExtensions 는 랜덤 관련으로 사용합니다.
public struct Walker : IComponentData
{
public float ForwardSpeed;
public float AngularSpeed;
public static Walker Random(uint seed)
{
var random = new Random(seed);
return new Walker()
{
ForwardSpeed = random.NextFloat(0.1f, 0.8f),
AngularSpeed = random.NextFloat(0.5f, 4),
};
}
}
Walker 구조체에도 Random을 추가해 줍니다.
public struct Dancer : IComponentData
{
public float Speed;
public static Dancer Random(uint seed)
{
return new Dancer()
{
Speed = new Random(seed).NextFloat(1, 8)
};
}
}
Dancer 구조체 역시 Random을 추가해 줍니다.
이제 스폰을 컨트롤 하는 부분을 제작해 보겠습니다.
using Unity.Entities;
using UnityEngine;
public struct Config : IComponentData
{
public Entity Prefab;
public float SpawnRadius;
public int SpawnCount;
public uint RandomSeed;
}
public class ConfigAuthoring : MonoBehaviour
{
public GameObject Prefab = null;
public float SpawnRadius = 1;
public int SpawnCount = 10;
public uint RandomSeed = 100;
class Baker : Baker<ConfigAuthoring>
{
public override void Bake(ConfigAuthoring src)
{
var data = new Config()
{
Prefab = GetEntity(src.Prefab, TransformUsageFlags.Dynamic),
SpawnRadius = src.SpawnRadius,
SpawnCount = src.SpawnCount,
RandomSeed = src.RandomSeed,
};
AddComponent(GetEntity(TransformUsageFlags.None), data);
}
}
}
Config IComponentData를 만들어줍니다.
Entity 는 기존에서 사용하던 Prefab과 동일합니다.
Config에 속해 있는 데이터는 스폰을 어떤것을 얼마나 어떻게 할것인가에 가깝습니다.
이제 실제 스폰을 시키는 부분입니다.
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct SpawnSystem : ISystem
{
public void OnCreate(ref SystemState state)
=> state.RequireForUpdate<Config>();
public void OnUpdate(ref SystemState state)
{
var config = SystemAPI.GetSingleton<Config>();
var instances = state.EntityManager.Instantiate
(config.Prefab, config.SpawnCount, Allocator.Temp);
var rand = new Random(config.RandomSeed);
foreach (var entity in instances)
{
var xform = SystemAPI.GetComponentRW<LocalTransform>(entity);
var dancer = SystemAPI.GetComponentRW<Dancer>(entity);
var walker = SystemAPI.GetComponentRW<Walker>(entity);
xform.ValueRW = LocalTransform.FromPositionRotation
(rand.NextOnDisk() * config.SpawnRadius, rand.NextYRotation());
dancer.ValueRW = Dancer.Random(rand.NextUInt());
walker.ValueRW = Walker.Random(rand.NextUInt());
}
state.Enabled = false;
}
}
기본 구성은 이전 ECS의 System과 동일합니다.
partial struct로 구성되며 ISystem을 구현합니다.
추가된것은 OnCreate를 구현하였는데 여기에 state.RequireForUpdate<Config>()가 추가 되었는데 Config가 있기 전까지는 실행되지 않는다는 것 입니다.
OnCreate 에서 Config가 있는지를 확인한 후 Config가 있다면 SpawnSystem이 생성됩니다.
이후 OnUpdate는 자동으로 수행되며 Config에 있는 정보를 가지고 객체들을 스폰 시킨 후 마지막에 자신은 Enabled = false처리 됩니다.
Enabled = false처리가 되지 않는다면 매 Update마다 스폰을 시키게 됩니다.
ConfigAuthoring 에 입력된 데이터 입니다.
5천개가 입력되었습니다.
실행 화면입니다.
5천개의 Strawman 이 스폰된 것을 볼 수 있습니다.
'Unity Engine' 카테고리의 다른 글
[Unity]ECS - BurstCompile (1) | 2023.12.21 |
---|---|
[Unity]ECS (1) | 2023.12.05 |
[Unity] Animation Controller (0) | 2023.04.23 |
[Unity] ScriptableObject + Reflection (0) | 2023.03.28 |
[Unity]Job System + String (0) | 2023.03.03 |