タイルごとにゲームオブジェクトを作成せずに手続き型タイルマップを作成する効率的な方法を見つけるために、インターネットを検索してきました。私が見つけたすべてのTileMapチュートリアルは、何百ものGameObjectを作成してタイルを作成しています。したがって、Unityの階層は予想外に拡大しています。
これは「正しい」方法ではないと確信しています。特に、タイルマップをサポートする新しいUnity 2Dツールを見た後、Unityはそうしました。タイルごとではなく、「1つの」ゲームオブジェクトでタイルを作成できます。
では、正しく効率的な方法でタイルを作成するにはどうすればよいですか?
コメント
- あなたは'これを2つのSEサイトにクロス投稿しました。1つ選択してください。
- 内容'多数のゲームオブジェクトを作成することに特に関心がありますか?'階層が乱雑な場合は、簡単に修正できます。Unity'のバッチ処理では、とにかく類似のタイルを1つのバッチに結合する必要があるため、'この方法で行うと、ドローコールの大きなペナルティが発生する可能性は低くなります。オフスクリーンタイルを最小限に抑え、タイル更新機能に費やされた時間も両方とも解決可能な問題です。ゲームのプロファイルを作成し、特定のものを特定しましたか? cボトルネック'解決しようとしていますか?
- @DMGregory画面に100 * 100の地図があるとしたら(ズームアウトして全体を表示すると仮定した場合)マップ)、シーン内に10.000のゲームオブジェクトを作成します。また、10.000の不要な変換コンポーネントを意味します。 'ユニティが階層ウィンドウで10.000オブジェクトをサポートできるかどうかさえわかりません。数百回後にフリーズすることはわかっています。
回答
私が知っていることは次のとおりです:
オプション1.タイルごとのGameObject。場合によっては完全にひどいわけではありません。ニーズによっては、十分に機能する可能性があります。
オプション2。実行時に作成するテクスチャを参照する単一の四角形または平面。基本的に、タイルアトラステクスチャを使用して、マップを1つの新しいテクスチャとして「ペイント」します。もちろん、マップのサイズによっては、それぞれがマップの一部を表す複数の四角形/平面が必要になる場合があります。
オプション3.独自のメッシュを作成します。これは、一度実装したときに最も好む方法である可能性が高いです。 「非常に高い柔軟性とおそらく最高のパフォーマンスが得られます。基本的に、タイルごとにクワッドを作成し、各頂点のUVを設定して、タイルアトラスのタイルにマッピングします。
オプション2の場合、I」 d quill18createsによるこのビデオシリーズの視聴をお勧めします: quill18createsによる3DTileMapチュートリアルシリーズ
オプション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; }
コメント
- あなたの答えは私を助けてくれました日々。今、私は古い質問を調べていますが、' 'この回答が受け入れられたことを確認したことがないことに気付きました。承認が1年遅れて申し訳ありません^^回答ありがとうございます。
回答
あなたとして(私は思う)ほのめかされているように、Unityのロードマップにはタイルマップエディターの計画があります。今のところ、進め方が少し混乱しているので、楽しみにしています。
それまでの間、最善のアプローチは「タイルでマップを作成し、X-UniTMXを使用してUnityにインポートすることをお勧めします。明らかに、これは手続き型生成ではありません。X-UniTMXがメッシュの作成に使用しているのと同じ手法を使用すると思います。
回答
タイルを階層のより深いところに作成し、そのフォルダーを閉じて、煩わされることはありません。同様にできることは、階層からゲームオブジェクトを非表示にすることです `myTile.hideFlags = HideFlags。 HideInHierarchy」では、どの程度のパフォーマンスが得られるかわかりません。
100x100のテクスチャを画面に表示することは、テクスチャの描画がポリゴンの描画よりも重いことは決して良い考えではありません。ズームアウトする必要がある場合は、テクスチャを大きくする方がよいでしょう。ズームインする場合も同様です。描画する必要のないテクスチャを描画しないでください。
私が通常行うこと(私は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); } }
私が使用しているdrawメソッドは、GUIを描画するためのもののようですが、タスクに完全に適している可能性があります。それ以外の場合は、スプライトマネージャーを調べて方法を見つける必要があります。これはこのメソッドで機能します。
タイルクラスのint 1
がテクスチャを参照し、は別のものを指します。テクスチャを描画している線では、辞書を使用して適切なテクスチャオブジェクトを指定します。このようにすると、GameObjectが作成されないため、不要なオーバーヘッドがすべて作成されることはありません。
GameObjectの制御レベルを必要としないほとんどすべての場合に同じことができます。ただし、この方法では、マップのすべてのタイルが描画されます。おそらく、ゲームオブジェクトの場合のように、オブジェクトを自動カリングすることはありません。しかし、画面に表示する必要があるものを描画するだけで非常に簡単です。画面/ビューポートのサイズ、カメラの位置、タイルのサイズを知っています。いくつかの簡単な数学は、必要なものを正確に描く必要があります。
それでも、ユニティは3Dエンジンです。3Dの方法で2Dをサポートするだけです。ただし、基本的に、テクスチャを使用したクワッド/メッシュに対して同じことを行うことができます。正投影カメラ。必要なメッシュを描画するだけでかなり安価です。
回答
ボクセル/ブロックベースのプロジェクトに取り組んでいる人として、2Dでのみ、同じアプローチを使用することを考えずにはいられません。グリッドのようなメッシュを手続き的に構築し、テクスチャアトラスのタイルビジュアルの正しい座標をUVチャネルに割り当てることができます。3Dでは、さらに多くの作業を行う必要があります。これよりも高いパフォーマンスが得られますが、2Dでは十分である可能性が高いです。
回答
いつでもLeanPoolを使用できます。アセットストアの無料アセット。それはあなたのためにオブジェクトプーリングを行います。次に、カメラビューの周囲で単純なカリングシステムを実行して、タイルゲームオブジェクトがカメラビューに出入りするときにそれらをスポーン/デスポーンします。タイルマップの大きさはわかりませんが、Unityはかなりの数のゲームオブジェクトを処理できます。 LeanPoolにはUnityのベンチマークシーンがあり、ボックスコリジョンコンポーネントを使用して1000個のオブジェクトをスポーン/デスポーンできます。おそらく、それぞれにレンダリングコンポーネントもあり、非常に高速に実行されます。
https://gamedevacademy.org/how-to-script-a-2d-tile-map-in-unity3d/
ここに表示されるリンクがありますタイルマップでLeanPoolを使用する例。