ECS(Entity Component System) 튜토리얼: Step 6 - 많은 탱크들을 소환(Spawning many tanks)
Unity 2022. 11. 30. 08:46Step 6 - 많은 탱크들을 소환(Spawning many tanks)
한 번만 실행되어야 하는 초기화 시스템을 처리.
- "Tank" Game Object를 "EntityScene"에서 "Assets/Prefabs" 폴더로 드래그 앤 드롭합니다.
- "EntityScene"에서 "Tank" GameObject(현재는 프리팹 인스턴스)를 삭제합니다.
- "Scripts/Components" 폴더에 "Config.cs"이라는 이름의 새 C# 스크립트 파일을 만들고 다음 내용을 저장합니다:
-
using Unity.Entities; struct Config : IComponentData { public Entity TankPrefab; public int TankCount; public float SafeZoneRadius; }
- "Scripts/Authoring" 폴더에 "ConfigAuthoring.cs"이라는 이름의 새 C# 소스 파일을 만들고 다음 내용을 저장합니다:
-
using Unity.Entities; class ConfigAuthoring : UnityEngine.MonoBehaviour { public UnityEngine.GameObject TankPrefab; public int TankCount; public float SafeZoneRadius; } class ConfigBaker : Baker<ConfigAuthoring> { public override void Bake(ConfigAuthoring authoring) { AddComponent(new Config { TankPrefab = GetEntity(authoring.TankPrefab), TankCount = authoring.TankCount, SafeZoneRadius = authoring.SafeZoneRadius }); } }
- Hierarchy 창에서 "EntityScene"을 마우스 오른쪽 단추로 클릭하고 Create Empty를 선택한 다음 새 GameObject의 이름을 "Config"로 지정합니다.
- "ConfigAuthoring" 컴퍼넌트를 "Config" GameObject에 추가합니다.
- "Config" GameObject를 선택하고, 프로젝트 폴더에서 새 필드 "TankPrefab"을 "Tank" 프리팹(드래그 & 드롭)으로 설정하고, "TankCount"를 20으로 설정하고, "SafeZoneRadius"를 15로 설정합니다.
📝 NOTE"SafeZone Radius"는 아직 사용되지 않지만 이후 진행될 튜토리얼과 관련이 있습니다. - "Scripts/Systems" 폴더에 "TankSpawningSystem.cs"이라는 이름의 새 C# 스크립트 파일을 만들고 다음 내용을 저장합니다.
⚠ WARNING이 시점에서 플레이 모드로 들어가면 탱크가 하나밖에 없다는 사실에 놀랄 수 있습니다. 실제로 20개의 탱크가 있지만, 그들은 모두 같은 위치에서 스폰되고 정확히 같은 방식으로 움직입니다. -
using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Mathematics; using Unity.Rendering; [BurstCompile] partial struct TankSpawningSystem : ISystem { [BurstCompile] public void OnCreate(ref SystemState state) { } [BurstCompile] public void OnDestroy(ref SystemState state) { } [BurstCompile] public void OnUpdate(ref SystemState state) { var config = SystemAPI.GetSingleton<Config>(); var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>(); var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged); var vehicles = CollectionHelper.CreateNativeArray<Entity>(config.TankCount, Allocator.Temp); ecb.Instantiate(config.TankPrefab, vehicles); // 이 시스템은 시작할 때 한 번만 실행해야 합니다. 따라서 한 번 업데이트하면 자동으로 비활성화됩니다. state.Enabled = false; } }
- 다음과 같이 "Scripts/Systems" 폴더에 있는 "TankMovementSystem.cs" 파일의 내용을 수정합니다:
-
using Unity.Entities; using Unity.Mathematics; using Unity.Transforms; partial class TankMovementSystem : SystemBase { protected override void OnUpdate() { var dt = SystemAPI.Time.DeltaTime; Entities .WithAll<Tank>() - .ForEach((TransformAspect transform) => + .ForEach((Entity entity, TransformAspect transform) => { var pos = transform.Position; + // 이는 탱크의 실제 위치를 수정하는 것이 아니라 3D 노이즈 기능을 샘플링하는 지점만 수정합니다. + // 이 방식으로, 모든 탱크는 다른 파츠를 사용하고 있으며 고유한 랜덤 플로우 필드를 따라 이동합니다. + pos.y = entity.Index; var angle = (0.5f + noise.cnoise(pos / 10f)) * 4.0f * math.PI; var dir = float3.zero; math.sincos(angle, out dir.x, out dir.z); transform.Position += dir * dt * 5.0f; transform.Rotation = quaternion.RotateY(angle); }).ScheduleParallel(); } }
- 플레이 모드로 들어가면, 20개의 탱크가 각각의 흐름 필드를 따라 이동하기 시작합니다.
- 플레이 모드를 종료하세요.