코딩/유니티

[Unity] 3D 랜덤 맵 생성 2

Hun die 2023. 5. 23. 17:23
최적화

이전에는 PerlinNoise를 활용해서 맵을 만들었다.

이제 만들어진 맵을 최적화 해보려고 한다.

 

이전화에는 숨겼지만, 사실 메쉬가... 어마어마하게 많이 잡힌다.

저 상태에서 움직이면 렉도 걸림 ㅎㅎ;

이는 블록 하나하나가 6면체를 메쉬하기 때문인데 보이지 않는 부분은 메쉬를 없애줄 필요가 있다.

 

메쉬 재생성

 

그래서 블록의 메쉬를 가져와 Vertices과 Triangles을 건드려 수정하기로 했다.

메쉬 부분은 이분의 블로그를 참고했다.

https://dongyeopblog.wordpress.com/2016/08/15/unity-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EB%B0%95%EC%8A%A4%EB%A7%8C%EB%93%A4%EA%B8%B0cube/

 

Unity 스크립트로 박스만들기(Cube)

유니티에서 3D파일을 사용하지않고 스크립트로 박스를 만드는코드입니다. C#으로 Start()에 넣어주신후 임의의 오브젝트를 생성후 게임을 실행하면 런타임에서 도형이 그려지는것을 확일할 수 있

dongyeopblog.wordpress.com

메쉬의 점 부분 

private void SetVertices()
    {
        vertices = new Vector3[24];

        Vector3 v0 = Vector3.Scale(new Vector3(+0.5f, +0.5f, +0.5f), size) + offset;
        Vector3 v1 = Vector3.Scale(new Vector3(-0.5f, +0.5f, +0.5f), size) + offset;
        Vector3 v2 = Vector3.Scale(new Vector3(-0.5f, -0.5f, +0.5f), size) + offset;
        Vector3 v3 = Vector3.Scale(new Vector3(+0.5f, -0.5f, +0.5f), size) + offset;
        Vector3 v4 = Vector3.Scale(new Vector3(-0.5f, +0.5f, -0.5f), size) + offset;
        Vector3 v5 = Vector3.Scale(new Vector3(+0.5f, +0.5f, -0.5f), size) + offset;
        Vector3 v6 = Vector3.Scale(new Vector3(+0.5f, -0.5f, -0.5f), size) + offset;
        Vector3 v7 = Vector3.Scale(new Vector3(-0.5f, -0.5f, -0.5f), size) + offset;

        vSet = new Vector3[] {
            v0, v1, v2, v3, v4, v5, v6, v7
        };
    }

메쉬의 면 부분

private int[] setMeshData(BlockFace face)
    {
        int[] AddTriangles = new int[6];

        vertices[((int)face * 4) + 0] = vSet[faceNumber[(int)face][0]];
        vertices[((int)face * 4) + 1] = vSet[faceNumber[(int)face][1]];
        vertices[((int)face * 4) + 2] = vSet[faceNumber[(int)face][2]];
        vertices[((int)face * 4) + 3] = vSet[faceNumber[(int)face][3]];

        AddTriangles[0] = (((int)face + 1) * 4) - 4 + 0;
        AddTriangles[1] = (((int)face + 1) * 4) - 4 + 1;
        AddTriangles[2] = (((int)face + 1) * 4) - 4 + 3;
        AddTriangles[3] = (((int)face + 1) * 4) - 4 + 1;
        AddTriangles[4] = (((int)face + 1) * 4) - 4 + 2;
        AddTriangles[5] = (((int)face + 1) * 4) - 4 + 3;

        return AddTriangles;
    }

 

그리고 주변의 블록을 감지하는 기능도 만들었다.

 

주변 블록을 감지한 결과

그리고 블록이 있으면 메쉬를 지우고 블록이 없는 null 값이라면 메쉬를 추가했다.

메쉬 처리 후

메쉬를 처리한 모습이다.

 

이전과 다를게 없어 보이지만, 블록의 간격을 벌려보면?

 

만들어진 메쉬가 겉에만 존재하고 내부는 비어있는 것을 볼수있다!

 

이걸로도 충분한 최적화는 되었다고 생각하지만 아직 멀었다.

 

메쉬 합치기

유니티에는 CombineInstance를 활용해 메쉬를 합칠 수 있다.

	CombineInstance[] combine = new CombineInstance[meshFilters.Count];

        for (int i = 0; i < meshFilters.Count; i++)
        {
            combine[i].mesh = meshFilters[i].sharedMesh;
            combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
            meshFilters[i].gameObject.SetActive(false);
        }
        GetComponent<MeshFilter>().mesh.CombineMeshes(combine);

CombineInstance배열을 넣고 위치를 잡아주고 메쉬를 가져온 오브젝트는 비활성화 해준다.

합쳐진 메쉬

이렇게 '청크'를 만들고 최적화까지 했다.

 

이게 이렇게 만든 청크를 늘리니 그럴듯한 맵이 되었다.

3 * 3
10 * 10