인프런 커뮤니티 질문&답변
ecs관심이 있었는데 강의 잘 보았습니다.
작성
·
40
0
현재 강의는 심화과정 2강의 빼고 다 보았습니다. 몇가지 궁금한 사항들이 있어서 질문드리려고 합니다.
ecs, dots 병렬처리를 위해서 유니티에서 사용하는 시스템인데요.
이 강의에서도 여러 쓰레드를 사용하기 위해 잡에 작업들을 할당하는 코드를 사용하는 것으로 보입니다.
그리고 발사체와 적이 충돌시 HP를 깍는데 EnemyComponentLookup[enemy] = enemyData;
이런 코드가 있던데 이는 실제로 해당 컴포넌트에서 hp 변수를 수정하는 내용으로 보입니다.
하지만 멀티쓰레드에서 lock이나 뮤텍스같은 안전장치가 없는데 저런식으로 사용할 수 있는지 묻고 싶고...
두번째는
Enemy오브젝트에서 여러 엔티티 update 이벤트를 사용하고 있습니다. EnemyComponent는 발사체에서도 사용하고 있고 moveComponent에서도 사용하고 있고 hpBarComponent에서도 사용하고 있습니다.
Enemy가 죽었을때 수십만 이벤트가 현재 할당된 상태에서 문제가 없는것인지 추가적인 내용을 알 고 싶습니다.
현재 만마리 이상 스폰을 시키면 간혹 죽은 Enemy들이 살아있는 것 같은데 ecs, 멀티쓰레드 강의에서 젤 중요한 내용이 빠진게 아닌가 싶어서 여쭈어봅니다.
답변 2
0
안녕하세요. Sura J 님,
좋은 질문 감사합니다.
1번째 질문에 대한 답변입니다.
Unity ECS는 컴파일 타임에 데이터 레이스컨디션을 감지합니다. 즉, Burst 컴파일러와 함께 사용될 때, Unity ECS는 시스템이 접근하는 데이터에 대한 읽기 및 쓰기 권한을 분석하여 데이터 레이스를 방지합니다. 그리고, ITriggerEventsJob 은 각 충돌 이벤트마다 Execute 메서드가 독립적으로 호출됩니다. 즉, 각 충돌 이벤트는 별도의 작업으로 처리되며, 이로 인해 레이스가 발생할 가능성이 줄어듭니다.
충돌처리가 미스하는 Enemy가 보인다고 하셨는데, 아마도 동일한 엔티티에 대해 여러 충돌 이벤트가 동시에 발생했을 발생하는 것으로 추측됩니다.(정확하지는 않지만) 따라서 값을 직접 변경하는데신 EntityCommandBuffer 사용하거나 NaviveQueue를 사용하는 것도 고려해볼 수 있습니다.
이 부분은 저도 테스트를 해봐야 할 것 같습니다.
[ReadOnly] 속성과 Job Dependency로 기본적으로 thread-safe한 구조를 제공하지만, 특정 상황에서는 추가적인 동기화 과정이 필요할 수 있을것 같습니다.
2번째 질문에 대한 답변입니다.
우선 만마리 이상의 경우 성능저하에 대한 우려에 대해 질문하셨는데요.
첫번재는 엔티티 수가 많을수록 Job 완료 대기 시간이 길어질수 있고, 두번째는 ComponentLookup의 캐시 미스가 증가할 수 있습니다. 코드를 검토해보고 개선할 수 있는 부분이 있는지 확인해 보았습니다. 우선 EnemyMovementSystem, EnemyHpBarSystem의 경우 시스템의 실행 순서를 명확히 명시하는 것이 좋을것 같습니다.
// EnemyMovementSystem
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(FixedStepSimulationSystemGroup))] // 충돌 처리 후 실행
partial struct EnemyMovementSystem : ISystem { ... }
// EnemyMovementSystem
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(FixedStepSimulationSystemGroup))] // 충돌 처리 후 실행
partial struct EnemyMovementSystem : ISystem { ... }강의에서는 적 캐릭터를 리스폰하지 않았지만 만약 리스폰 기능을 구현한다면 풀링 기법을 사용해 Enemy가 죽었을 때 Entity를 삭제하는 것이 아니라 비활성화하는 방법도 고려해볼 수 있습니다.
미쳐 생각하지 못했던 부분에 대해 좋은 질문을 해주셔서 감사합니다. 종합적으로 코드를 다시 한번 검토해보고 최적화할 수 있는 부분이 있는지 살펴보겠습니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다. Sura J님.
ECS와 DOTS를 활용한 유니티 프로그래밍에 관한 질문을 주셨는데요, 먼저 강의를 거의 완료하신 점에서 많은 노력을 기울이고 계시다는 것을 알 수 있습니다. 여러분이 제기한 두 가지 질문에 대해 설명드리겠습니다.
질문 1: 멀티쓰레드에서의 안전성 문제
ECS/DOTS에서는 Unity의 Job System을 사용하여 다중 스레드에서 작업을 병렬로 수행합니다. Job System은 데이터 중심의 설계를 가지고 있으며, 일반적으로 컴포넌트를 직접 수정하지 않고 Safety System이 안전한 상태를 유지하도록 합니다. 여기서 데이터 레이스 문제를 방지하기 위해 Unity는 특정한 제약을 가집니다.
- 데이터 접근: 컴포넌트 데이터를 읽고 쓰는 작업은 대부분 ReadOnly 모드나 동시성을 고려한 설계를 통해 이루어집니다. Unity에서 멀티스레드 작업 시, 데이터 접근에 있어 read/write conflicts가 자동적으로 관리됩니다.
- 잠금 및 동기화: Unity Job System 자체가 성능 상의 이점을 극대화하기 위해 가능한 한 잠금(mutex, lock 등)을 피하며, 매개 변수에 대한 올바른 접근(예: NativeArray, NativeQueue)을 통해 문제를 최소화합니다. 그럼에도 필요하다면 메인 스레드에서 동기화 작업을 수행할 수 있습니다.
질문 2: 이벤트 처리 및 성능 이슈
ECS/DOTS 구조에서 이벤트를 관리하는 방법도 고민되셨을 것입니다:
- 이벤트 시스템 설계: 이벤트가 많은 상황에서도 문제가 발생하지 않도록 하기 위해 일반적으로 이벤트 발행을 최소화하며, 필요할 경우 efficient한 구성 요소를 활용합니다. 예를 들어, 이벤트가 많은 상태에서는 버퍼(EntityCommandBuffer)나 큐를 활용해 이벤트를 모아 한번에 처리하는 식으로 디자인됩니다.
- 엔티티 관리: 대규모 엔티티 수명 주기를 관리하는 데 있어, 컴포넌트의 상태를 주기적으로 갱신하고 불필요한 엔티티를 메모리에서 해제하는 방법이 필요합니다. BounceEffectData 제공을 중단하거나 생명체가 사망하면 관련 엔티티를 빠르게 제거하여 성능 문제를 방지합니다.
추가참고
위 답변이 프로젝트에 도움이 되었으면 합니다. ECS와 DOTS 에서는 데이터 중심 설계와 작업의 병렬성이 중요한 만큼, 이러한 부분들을 명확히 이해하고 프로젝트에 적용하는 것이 중요합니다. 추가적인 질문이 있으시다면, 언제든지 이어서 질문해 주세요. 유익한 학습이 되시길 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





결국 ecs도 멀티쓰레드에 대한 문제가 존재하는 것이 보이는데, 이 강의에서 좀 더 멀티쓰레드에서 발생하는 문제에 대해서 설명을 주시면 더 좋은 내용이 될 것 같습니다.
답변 감사합니다.