이번 목표는 간단하다.
Physics Collider의 CollisionFilter의 BelongsTo 값을 팀에 따라 분리하는 것이다.
Collision Filter란 이 엔티티가 어떤 엔티티와 충돌을 할 지를 결정하는 것이다. 나의 경우 팀0은 BelongsTo 1<<6, 팀1은 BelongsTo 1<<7이 필요하다.
원래 유니티에서는 좀 더 간단히 해결했지만, DOTS 환경에서는 이것을 고치기 위해 unsafe가 필요하다.
먼저 이 filter를 바꾸려고 하는 이유를 말하자면.
현재 aabb방식으로 적 탐지와 공격 적용을 구현하고 있다. 그리고 이 aabb충돌 탐지에서 collisionFilter로 아군을 무시하게 하기 위함이다.
원래 방식은 적팀의 태그 컴포넌트의 ComponentLookup을 IJobEntity에 넘겨주고, 충돌이 생긴 엔티티들 중에서 태그 컴포넌트가 적팀인 엔티티인지 확인하는 조건문이 있었다.
단!
ComponentLookup은 랜덤 엑세스다. 즉 캐시 미스 확률이 있다는 것이다.
그래서 가급적이면 이 ComponentLookup을 안 쓰려고 노력하고 있다. 그러기 위해 서로 다른 팀은 다른 BelongsTo 레이어를 가지도록 하려는 것이다.
_____________________________________________________________________
문제:
Physics Collider는 유니티의 Baking과정을 거치면서, 똑같은 값을 가진 엔티티들의 physics Collider는 하나의 BlobAsset에 대한 포인터 참조를 하는 형태로 구현된다.
이게 무슨 말이냐면, 우리는 엔티티 하나하나마다 조건에 따라 CollisionFilter를 각각 수정할 수 없다는 것이다. 왜냐하면 얘네들은 전부 다 같은 값을 참조하고 있기 때문에, 하나를 바꾸면 모두가 똑같아진다.
그래서 SetCollisionFilter같은 함수로 설정을 해도, 같은 프리팹으로 만든 엔티티들은 팀 구분과 관계 없이 전부 다 똑같은 필터 값을 가지게 된다.
____________________________________________________________________
해결 방법:
포인터가 문제라면 포인터로 해결하면 된다.
(collider 복제 함수)
일단 유니티 설정에서 unsafe를 활성화한다.
Unsafe: C#에서 직접 메모리 관리를 하겠다는 신호
1. 현재 collider의 포인터를 얻어서 현재 collider를 복제해 온다.
2. 그리고 복제한 collider에서 원하는 filter를 설정한다.
3. collider 적용
4. 엔티티를 파괴할 때 여기서 할당된 메모리도 dispose하는 것을 잊으면 안된다.
이거 해결하느라 꼬박 하루 보냈다. 이제 lookupComponent을 써서 생기는 랜덤 엑세스로 인한 캐시 미스는 없다.
_______________________________________________________________________________
요 며칠 동안 최적화를 잡느라 엄청난 에너지를 쏟았다.
보통 프로젝트에서는 최적화를 가장 마지막에 하는데, DOTS라는 패러다임을 쓰고 있으므로 쉽사리 미룰 엄두를 못 내고 있다. 이런 형태로 개발을 진행하다가 맨 마지막에 수정을 할 수 있을 지에 대한 확신이 없기 때문이다.
물론 전통적인 방식의 최적화 방안들도 프로젝트 막바지에 적용 시킬 생각이다. DOTS는 그저 도구일 뿐이지 이것에 매몰되면 안된다. 그러므로 전투 시스템을 제외하면 모조리 oop로 딸깍할 예정이다.
어쨌든 상기 이유로 이제부터는 좀 더 기획에 쓰는 시간을 늘릴 예정이다.
댓글 0