한동안 블로그 포스팅이 뜸했는데 그간 작업한 내용을 정리해서 올려본다.
1) 유도 미사일이 목표를 정확하게 추적할 수 있도록 코드를 수정했다. 생각보다 빡셨다.
2) 로켓탄 외에 머신건과 라이플로 복셀을 파괴할 수 있도록 했다.
3)복수의 NPC들 처리.
복수의 NPC들을 집어넣자 문제가 생겼다.
우선 접속후 절차를 살펴보면…
- 플레이어가 접속하면 서버로부터 플레이어 주변의 복셀 지형을 bit table로 전송받는다.
- 이 bit table을 실제 사용할 데이터로 변환한다.
- 최적화된 충돌처리용 삼각형 데이터 생성 , 렌더링을 위한 압축된 버텍스 데이터와 인덱스 데이터 생성
- 버텍스 데이터와 인덱스 데이터를 Vertex Buffer/Index Buffer로 write.
- 라이트맵 계산을 위한 patch 리스트 생성
- 라이트맵 계산
- 라이트맵을 Texture로 갱신
- 이걸 한프레임 내에 다 하려면 눈에 거슬릴정도로 진행이 끊기기 때문에 한 프레임에 다 처리하지 않고 여러 프레임에 걸쳐 진행한다.
- 성능을 높이기 위해 이 작업은 여러개의 스레드가 동시에 처리한다. 각 스레드는 하나의 오브젝트씩을 처리하므로 동기화 문제는 없다. 처리가 완료될때까지 메인스레드는 wait한다.
그리고 문제가 생긴 경우를 보면 다음과 같다.
- NPC가 이미 서버에 들어가있음.
- 플레이어가 접속함.
- NPC가 플레이어를 공격하려고 움직임. 서버에서 클라이언트로 NPC가 움직이기 시작한다는 패킷이 전송됨.
- 클라이언트에선 현재 섹터(맵의 일정부분)의 복셀 데이터는 이미 수신했지만 이 데이터가 완전한 매시로 변환되기 전이다.
- 이 경우를 대비해서 충돌처리등을 하게 될 경우 해당 구역의 복셀 데이터는 즉시 충돌삼각형으로 변환된다. 문제는 이 코드가 멀티스레드용이 아니었다는 점. 애초에 이 경우는 메인 스레드에서 복셀을 픽킹하거나 하는 경우로 가정했었다.
- 충돌처리 또한 멀티스레드로 처리 되기 때문에 이 코드를 호출하면 문제가 된다.
- 패킷을 수신하거나 파일로부터 복셀 데이터를 읽었을 경우 멀티스레드로 변환을 수행하지만 코드 흐름이 완전히 달라서 같은 코드를 공유할수는 없다.
해결
아직 복셀 데이터를 완전히 변환하지 못했는데 충돌처리를 시도할 경우, 충돌처리 스레드(컨텍스트)에서만 사용 가능한 임시 메모리를 할당하고 충돌처리 삼각형을 즉시 변환해서 이 메모리에 써넣도록 했다. 적어도 충돌처리를 진행하는 도중에는 이 메모리를 사용해서 매번 변환을 할 필요는 없다. 여기서 사용하는 변환 코드는 스레드 세이프하다.
4) NPC들도 라이플과 머신건, 유도미사일을 사용할 수 있도록 했다.
NPC도 머신건, 라이플, 로켓런처, 유도탄 사용 가능.
NPC도 플레이어와 마찬가지로 복셀 파괴 가능.
복셀관련해서 궁금해서 검색하다 우연히 들어왔는데 읽다가 밤을 새버렸네요 이정도로 최적화나 기술적용에 대해서 차근차근 상세하게 써놓은 공개글은 처음봤어요 감사합니다 또 보러올게요
좋아요좋아요
감사합니다.
좋아요좋아요