큐브를 하나생성했으니 이제 많이 만들어보겠습니다
먼저 청크 시스템을 활용하겠습니다
수십만개의 블록을 하나의 메쉬로 다루게 된다면
후에 블록을 캤을 때 메쉬를 재계산하는 시간이 오래걸릴 것입니다
따라서 16x16x16크기의 청크단위로 메쉬를 생성하여 변화가 생길때 빠릿빠릿하게 계산할 수 있도록 하겠습니다
또 하나의 최적화 기법으로
보이지 않는 면, 즉 이웃한 블록이 공기블록(투명블록)일 경우에만 면을 그리도록 하겠습니다
일단 맵데이터를 생성하겠습니다
맵데이터란 어느좌표에 어떤 블록이 있는지를 적어놓은 맵 설계도입니다
이 맵 설계도를 토대로 해당 좌표에 어떤 블록이 올지를 정합니다
mapData는 3차원의 byte배열입니다
byte는 크기가 1바이트(8비트)로 엄청 용량이 적은 자료형입니다
어차피 제가 만들 게임은 블록을 10개도 안쓸것같으니 최적입니다
0을 공기블록으로 1을 흙 블록으로 설정하겠습니다
일단 되는지 안되는지 확인하는게 먼저니 모든 배열의 값을 1로 설정합니다
이제 청크를 생성하는 메소드를 짜보겠습니다
- 빈 메쉬를 생성합니다
- 맵 데이터를 세팅해줍니다
- Const int로 선언한 CHUNK_SIZE 만큼 x,y,z좌표를 순회하는 3중 for문을 사용합니다
- 먼저 해당 위치에 어떤 블록이 올지 검사합니다
공기 블록이면 (맵 데이터의 x,y,z인덱스 값이 0이면) 배치할 필요가 없으니 continue를 써줍니다
그렇지않다면 블록을 배치해야합니다 - origin을 현재 x,y,z좌표로 잡아줍니다
- 주변 블록을 검사하기 위해 IsTransparent라는 메소드를 생성했습니다
이 메소드는 주변블록이 공기이면 참 아니라면 거짓을 반환합니다
x,y,z좌표가 0이나 16인 경우에는 주변 블록을 검사할때 out of range 오류가 날 수도 있으니 임시로 예외처리를 해줍니다
7. 이제 주변블록이 공기블록이면 면을 그릴것입니다
면을 그리는 기능은 전에 쓰던 기능과 똑같습니다
8.최종적으로 만든 메쉬를 넣어주고
땅위에 서있고 싶으니 메쉬 콜라이더에도 메쉬를 넣어주겠습니다
이제 청크를 생성하면?
4096개의 블록을 생성했지만 180프레임을 뽑아내고있습니다...
이제 여러개의 청크를 생성해보겠습니다
그러려면 여러개의 게임오브젝트를 생성해야 합니다
하나의 청크를 하나의 게임오브젝트로 만들어 주겠습니다
이를 위해 CreateChunk 메소드를 변경하겠습니다
먼저 매개변수로 청크가 어디서부터 시작될지에 대한 Vector3 값을 받아옵니다
그리고 vertice, triangle, uv 리스트를 초기화해줘야 합니다
청크를 생성할때 마다 새로운 정보를 기입해줘야 하기 때문입니다
그리고 청크내에 블록들이 그려질 좌표에 대한 연산도 해줍니다
청크 사이즈는 16이고 하나의 청크마다 x든 y든 z든 16의 좌표가 이동될 것이기에
x,y,z방향의 청크 수 * 청크 사이즈 부터
x,y,z방향의 청크 수 * 청크 사이즈+청크사이즈 까지를 블록들이 그려질 시작좌표로 정해줍니다
청크가 될 게임오브젝트를 새로 만들어줍니다
생성자안에서 게임오브젝트의 이름과 갖고 태어날 컴포넌트를 정할 수 있습니다
맵 데이터또한 처리가 필요합니다
저희가 맵데이터를 설정할때는 크기 16x16x16의 단일 청크만 염두에 두고 설정했습니다
맵데이터의 인덱스가 15를 넘어가면 오류가 날것이기에 일단 임시방편으로 0~15로 제한을 해줍니다
나중에는 청크마다 다른 맵데이터를 설정해줘야겠지만 일단 하나의 맵데이터를 돌려쓰겠습니다
IsTransparent의 매개변수 x,y,z또한 값을 0~15로 제한하겠습니다
이제 공들여 만든 메쉬를 넘겨주겠습니다
새로 생긴 게임오브젝트의 메쉬렌더러의 머리티얼은 일단 본 스크립트에서 할당후에 넘겼습니다
이제 심판의 시간입니다...
과연 이번에도 렉이 걸릴까요...?
5x5x5사이즈로 125개의 청크
51만개의 블록을 생성해보겠습니다...
딸깍
(두근두근)
(감동)
블록수가 5배는 많지만
프레임이며 batch며 모든 게 압도적입니다...
뭔가... 뭔가가 되고있어요오오오옷
키야~
좃댄다
이렇게 수많은 오브젝트를 생성하면 저장시스템은 또 어떻게하는거임? 머리아프다
아직 프로젝트 초반인데 ecs로 전환하는 건 어떰? 51만 블록도 한 500fps 나올 수도 있을 텐데
너무 어려워욧