저는 타일별로 게임 오브젝트를 생성하지 않고 절차 적 타일 맵을 생성하는 효율적인 방법을 찾기 위해 인터넷을 검색했습니다. 제가 찾은 모든 TileMap 튜토리얼은 수백 개의 게임 오브젝트를 만들어 타일을 만드는 것입니다. 따라서 Unity의 계층 구조가 예기치 않게 확장되고 있습니다.
이것은 “올바른”방법이 아니라고 확신합니다. 특히 타일 맵을 지원하는 새로운 Unity 2D 도구를보고 나면 Unity가 그렇게했습니다. 각 타일이 아닌 “하나의”게임 오브젝트에서 타일을 만들 수 있습니다.
그러면 어떻게하면 적절하고 효과적인 방법으로 할 수 있습니까?
댓글
- '이를 두 개의 SE 사이트에 교차 게시했습니다. 하나를 선택하세요.
- 내용 ' 여러 게임 오브젝트를 만드는 데 특별한 관심이 있으십니까? ' 계층 구조가 복잡하다면 쉽게 수정할 수있는 방법이 있습니다. Unity '의 일괄 처리는 어쨌든 유사한 타일을 단일 일괄 처리로 결합해야하므로 '이 방식으로 수행하는 데 따른 주요 드로우 콜 패널티가 될 가능성이 낮습니다. 화면 외부 타일 및 타일 업데이트 기능에 소요되는 시간도 해결할 수있는 문제입니다. 게임을 프로파일 링하고 특정 c 병목 현상을 ' 해결하려고합니까?
- @DMGregory 화면에서 100 * 100지도에 대해 생각한다면 (전체를보기 위해 축소했다고 가정하면 맵), 씬에 10.000 개의 게임 오브젝트가 생성됩니다. 또한 10.000 원치 않는 변환 구성 요소를 의미합니다. 저는 ' Unity가 계층 창에서 10.000 개체를 지원할 수 있는지조차 알지 못합니다. 수백 개 후에 멈춘다는 것을 알고 있습니다.
답변
알고있는 내용은 다음과 같습니다.
옵션 1. 타일 당 게임 오브젝트. 어떤 경우에는 완전히 끔찍하지 않습니다. 필요에 따라 작동 할 수 있습니다. 충분합니다.
옵션 2. 런타임에 생성 한 텍스처를 참조하는 단일 쿼드 또는 평면. 기본적으로 타일 아틀라스 텍스처를 사용하여 맵을 하나의 새 텍스처로 “페인트”합니다. 물론 맵의 크기에 따라 맵의 일부를 나타내는 여러 개의 쿼드 / 플레인을 가질 수 있습니다.
옵션 3. 자신 만의 메시를 생성합니다. 이것은 한 번 구현 한 후 가장 선호하는 방법 일 것입니다. “엄청난 유연성과 최고의 성능을 제공합니다. 기본적으로 타일 당 쿼드를 만들고 각 정점 UV를 설정하여 타일 아틀라스의 타일에 매핑합니다.
옵션 2의 경우 I” d는 quill18creates의이 비디오 시리즈를 시청할 것을 제안합니다. quill18creates의 3D TileMap 튜토리얼 시리즈
옵션 3의 경우, 이것은 제 코드입니다. 따라서 완벽하지 않을 수 있습니다.
//For this, your GameObject this script is attached to would have a //Transform Component, a Mesh Filter Component, and a Mesh Renderer //component. You will also need to assign your texture atlas / material //to it. void Start() { meshFilter = GetComponent<MeshFilter>(); BuildMesh(); } public void BuildMesh() { int numTiles = mapSizeX * mapSizeY; int numTriangles = numTiles * 6; int numVerts = numTiles * 4; Vector3[] vertices = new Vector3[numVerts]; UVArray = new Vector2[numVerts]; int x, y, iVertCount = 0; for (x = 0; x < mapSizeX; x++) { for (y = 0; y < mapSizeY; y++) { vertices[iVertCount + 0] = new Vector3(x, y, 0); vertices[iVertCount + 1] = new Vector3(x + 1, y, 0); vertices[iVertCount + 2] = new Vector3(x + 1, y + 1, 0); vertices[iVertCount + 3] = new Vector3(x, y + 1, 0); iVertCount += 4; } } int[] triangles = new int[numTriangles]; int iIndexCount = 0; iVertCount = 0; for (int i = 0; i < numTiles; i++) { triangles[iIndexCount + 0] += (iVertCount + 0); triangles[iIndexCount + 1] += (iVertCount + 1); triangles[iIndexCount + 2] += (iVertCount + 2); triangles[iIndexCount + 3] += (iVertCount + 0); triangles[iIndexCount + 4] += (iVertCount + 2); triangles[iIndexCount + 5] += (iVertCount + 3); iVertCount += 4; iIndexCount += 6; } mesh = new Mesh(); //mesh.MarkDynamic(); if you intend to change the vertices a lot, this will help. mesh.vertices = vertices; mesh.triangles = triangles; meshFilter.mesh = mesh; UpdateMesh(); //I put this in a separate method for my own purposes. } //Note, the example UV entries I have are assuming a tile atlas //with 16 total tiles in a 4x4 grid. public void UpdateMesh() { int iVertCount = 0; for (int x = 0; x < mapSizeX; x++) { for (int y = 0; y < mapSizeY; y++) { UVArray[iVertCount + 0] = new Vector2(0, 0); //Top left of tile in atlas UVArray[iVertCount + 1] = new Vector2(.25f, 0); //Top right of tile in atlas UVArray[iVertCount + 2] = new Vector2(.25f, .25f); //Bottom right of tile in atlas UVArray[iVertCount + 3] = new Vector2(0, .25f); //Bottom left of tile in atlas iVertCount += 4; } } meshFilter.mesh.uv = UVArray; }
댓글
- 귀하의 답변이 일. 이제 이전 질문을 살펴보고 ' '이 답변을 수락 한 것으로 확인한 적이 없음을 깨달았습니다. 한 번만 늦게 승인 해 주셔서 죄송합니다 ^^ 답변 해 주셔서 감사합니다.
답변
)이 암시하는 것처럼 Unity의 로드맵에는 타일 맵 편집기에 대한 계획이 있습니다. 지금 당장은 진행 방법이 약간 혼란 스럽기 때문에 앞으로도 기대하고 있습니다.
그동안 가장 좋은 방법은 “Tiled에서 맵을 만든 다음 X-UniTMX를 사용하여 Unity로 가져 오는 것입니다. 분명히 그것은 절차 적 생성이 아닙니다. X-UniTMX가 메시를 생성하는 데 사용하는 것과 동일한 기술을 사용할 것이라고 생각합니다.
Answer
타일을 계층 구조에서 더 깊게 생성하고 해당 폴더를 닫고 귀찮게하지 마십시오. “myTile.hideFlags = HideFlags 계층에서 게임 개체를 숨길 수도 있습니다. HideInHierarchy “는 성능이 얼마나 향상 될지 확실하지 않습니다.
화면에 100×100 텍스처를 표시하는 것은 결코 좋은 생각이 아닙니다. 텍스처를 그리는 것이 어쨌든 다각형을 그리는 것보다 더 무겁습니다. 그 정도까지 축소해야한다면 더 큰 텍스처를 사용하는 것이 좋습니다. 확대 할 때도 마찬가지입니다. 그릴 필요가없는 텍스처는 그리면 안됩니다.
내가 일반적으로하는 일은 (전 Unity 사람이 아닙니다) 맵에 대한 클래스를 만들고 사용하는 것입니다. 모든 타일을 보관하기위한 2 차원 배열입니다.이 배열은 단순히 int 또는 텍스처, 타일 유형, 객체 등을 참조하는 몇 개의 int가있는 Tile 클래스 일 수 있습니다. 그런 다음 다음과 같이 그립니다.
for (int y = 0; y < mapHeight; y++) { for(int x = 0; x < mapHeight; x++) { Graphics.DrawTexture(new Rect(x * tileWidth, y * tileHeight, tileWidth, tileHeigt), tileTexture); } }
제가 사용하는 그리기 방법은 GUI를 그리는 데 사용되는 것 같지만 작업에 완벽하게 적합 할 수 있습니다. 그렇지 않으면 스프라이트 관리자를 살펴보고 방법을 찾아야합니다. 이 방법으로 작동합니다.
타일 클래스에서 int 1
와 같은 텍스처 참조에 사전을 사용할 수 있으며 일부 텍스처는 는 다른 것을 나타냅니다.텍스처를 그리는 선에서 사전을 사용하여 올바른 텍스처 개체를 제공합니다. 이렇게하면 GameObject를 생성하지 않고 불필요한 오버 헤드를 모두 생성하지 않습니다.
GameObject의 제어 수준이 필요하지 않은 거의 모든 항목에 대해 동일한 작업을 수행 할 수 있습니다. 하지만 이렇게하면 맵의 모든 타일을 그릴 것입니다. 내가 생각하기에 게임 오브젝트와 일치하는 것처럼 오브젝트를 자동 컬링하지는 않습니다. 그러나 화면에 필요한 것을 그리는 것은 매우 쉽습니다. 화면 / 뷰포트 크기, 카메라 위치 및 타일 크기를 알고 있습니다. 간단한 수학은 필요한 것을 정확히 그려야합니다.
그래도 Unity는 3D 엔진입니다. 3D 방식으로 2D 만 지원합니다.하지만 기본적으로 텍스처가있는 쿼드 / 메쉬에 대해 동일한 작업을 수행 할 수 있습니다. 직교 카메라. 필요한 메시를 그리는 것만으로도 매우 저렴합니다.
답변
복셀 / 블록 기반 프로젝트에서 작업하는 사람으로서 , 저는 2D에서만 동일한 접근 방식을 사용하는 것에 대해 생각할 수밖에 없습니다. 절차 적으로 그리드와 같은 메시를 구축하고 텍스처 아틀라스의 타일 비주얼 좌표를 UV 채널에 할당 할 수 있습니다. 3D에서는 훨씬 더 많은 작업을 수행해야합니다. 이보다 높은 성능을 갖기에는 충분하지만 2D에서는 “정말로 충분합니다.
Answer
항상 LeanPool을 사용할 수 있습니다. . 자산 스토어의 무료 자산입니다. 그것은 당신을 위해 개체 풀링을 수행합니다. 그런 다음 카메라 뷰에 들어가거나 나올 때 타일 게임 오브젝트를 스폰 / 드 스폰하는 카메라 뷰 주변에서 간단한 컬 시스템을 수행 할 수 있습니다. 타일 맵이 얼마나 커질 지 잘 모르겠지만 Unity는 꽤 많은 게임 오브젝트를 처리 할 수 있습니다. LeanPool은 Unity에서 박스 충돌 구성 요소를 사용하여 수천 개의 오브젝트를 생성 / 디스 폰 할 수있는 벤치 마크 씬을 보유하고 있으며, 각 구성 요소에서 렌더링 구성 요소도 가능하다고 생각하며 매우 빠르게 수행합니다.
https://gamedevacademy.org/how-to-script-a-2d-tile-map-in-unity3d/
다음은 귀하를 보여주는 링크입니다. LeanPool을 타일 맵과 함께 사용하는 예입니다.