/// <summary> 시야범위 내의 청크 생성 </summary>
public void UpdateChunksInViewRange()
{
_prevActiveChunks = _currentActiveChunks;
_currentActiveChunks = new();
for (int x = -WorldData.ViewChunkRange; x <= WorldData.ViewChunkRange; x++)
{
for (int z = -WorldData.ViewChunkRange; z <= WorldData.ViewChunkRange; z++)
{
if (_chunkMap.TryGetValue(_currentPlayerCoord + new ChunkCoord(x, z), out var currentChunk))
{
_currentActiveChunks.Add(currentChunk);
currentChunk.SetActive(true);
_prevActiveChunks.Remove(currentChunk);
// NavMesh Source 전달
_navMeshBuilder.UpdateChunkSources(_currentActiveChunks);
}
}
}
foreach (var chunk in _prevActiveChunks)
chunk.IsActive = false;
_navMeshBuilder.UpdateNavMesh();
}
기존에는 청크가 활성화 될 때마다 WorldNavMeshBuilder 클래스에게 source를 갱신하도록 요청하고 있었는데, 이 로직의 문제가 있었다.
활성화되는 청크가 여러개일 경우, source 갱신의 요청도 여러번된다. 불필요한 연산이 발생하는 것이다.
public AsyncOperation UpdateNavMesh(Action<AsyncOperation> callback = null)
{
UpdateChunkSources(Managers.Game.World.CurrentActiveChunks);
if (_data == null || _sources == null)
return null;
var buildSettings = NavMesh.GetSettingsByID(0);
var bounds = CalculateViewBounds();
var op = NavMeshBuilder.UpdateNavMeshDataAsync(_data, buildSettings, _sources, bounds);
op.completed += callback;
return op;
}
WorldNavMeshBuilder 클래스에서 source의 변경을 클래스 외부에서 따로 하지 않고, nav mesh의 갱신 요청만 받도록한 다음, nav mesh 갱신 시 source도 함께 갱신하도록 구조를 변경했다.
우리 프로젝트 캐릭터에 점프는 추가하지 않을 예정이다.
하지만 맵은 Voxel 큐브 형태라서, 플레이어 캐릭터가 y축 이동을 할 수단이 필요하다.
좌측 섬, 우측 섬에는 산도 추가될 예정이기 때문에 오르락 내리락 할 Block을 추가했다.
스크립터블 오브젝트로 여러가지 Material을 설정할 수 있도록 했다.
현재 구현돼있는 일반 Block처럼 한 개의 Material로 uv 정보만 바꿔서 텍스처링 하고싶었지만,
그러기엔 개발이 너무 지체될 것 같아서 이런 방식을 택했다 .....
또 Forward라는 속성을 추가해서 어디를 바라보는지의 정보. 즉, Block의 회전 정보도 지정할 수 있게 했다.
Chunk.cs
private void AddVoxelDataToChunk(Vector3Int pos, BlockType block)
{
if (block is NormalBlockType normalBlock)
{
for (int i = 0; i < 6; i++)
{
if (_world.CheckVoxel(pos + _data.faceChecks[i]))
continue;
for (int j = 0; j < 4; j++)
_vertices.Add(pos + _data.voxelVerts[_data.voxelTris[i][j]]);
AddTextureUV(normalBlock.GetTextureID(i));
_triangles.Add(_vertexIdx);
_triangles.Add(_vertexIdx + 1);
_triangles.Add(_vertexIdx + 2);
_triangles.Add(_vertexIdx + 2);
_triangles.Add(_vertexIdx + 1);
_triangles.Add(_vertexIdx + 3);
_vertexIdx += 4;
}
}
else if (block is SlideBlockType slideBlock)
{
var obj = Managers.Resource.GetCache<GameObject>("Slide Block.prefab");
obj = UnityEngine.Object.Instantiate(obj, pos, Quaternion.identity);
var slide = obj.GetComponent<SlideBlock>();
slide.Forward = slideBlock.Forward;
slide.FrontMaterial = slideBlock.FrontMaterial;
slide.SideMaterial = slideBlock.SideMaterial;
slide.transform.SetParent(_chunkObject.transform);
}
}
현재 블록의 타입이 NormalBlock과 SlideBlock으로 나뉘게 됐는데, 청크가 블록을 생성하는 과정에서 if문으로 타입매칭을 하고 있다.
이 부분을 Switch문의 패턴매칭으로 바꾸던지, 가상 메서드를 이용하던지 해야겠다.
아마 가상 메서드가 더 객체지향적이지 않을까?