前提・実現したいこと
Graphics.DrawMeshを使って、正方形のメッシュを大量に描画したい。
該当のソースコード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ExampleClass : MonoBehaviour { Mesh mesh; public Material material; private void Start() { mesh = new Mesh(); mesh.vertices = new Vector3[] { new Vector3 (-1f, -1f, 0), new Vector3 (-1f, 1f, 0), new Vector3 (1f , -1f, 0), new Vector3 (1f , 1f, 0), }; mesh.uv = new Vector2[] { new Vector2 (0, 0), new Vector2 (0, 1), new Vector2 (1, 0), new Vector2 (1, 1), }; mesh.triangles = new int[] { 0, 1, 2, 1, 3, 2, }; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } void Update() { Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.AngleAxis(0.0f, new Vector3(1.0f, 0.0f, 0.0f)), material, 0); } }
試したこと
正方形のメッシュをGraphics.DrawMeshを使って描画しました。ですが、100×100のように、メッシュを大量に描画するやり方が分かりません。
試行錯誤しましたが、どうやっていいか、どうしても分かりませんでした。エラーは出ていません。
やり方を教えていただけると有り難いです。回答よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
ループを回して何度もDrawMeshを実行すればいいかと思いますが、それではうまくいかなかったでしょうか?
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class ExampleClass : MonoBehaviour 6{ 7 Mesh mesh; 8 Vector3[] positions; 9 Quaternion[] rotations; 10 int count; 11 public Material material; 12 public int rows = 100; // 行数 13 public int columns = 100; // 列数 14 15 private void Start() 16 { 17 mesh = new Mesh(); 18 mesh.vertices = new Vector3[] { 19 new Vector3 (-1f, -1f, 0), 20 new Vector3 (-1f, 1f, 0), 21 new Vector3 (1f , -1f, 0), 22 new Vector3 (1f , 1f, 0), 23 }; 24 25 mesh.uv = new Vector2[] { 26 new Vector2 (0, 0), 27 new Vector2 (0, 1), 28 new Vector2 (1, 0), 29 new Vector2 (1, 1), 30 }; 31 32 mesh.triangles = new int[] { 33 0, 1, 2, 34 1, 3, 2, 35 }; 36 37 mesh.RecalculateNormals(); 38 mesh.RecalculateBounds(); 39 40 count = rows * columns; 41 positions = new Vector3[count]; 42 rotations = new Quaternion[count]; 43 for (var i = 0; i < rows; i++) 44 { 45 for (var j = 0; j < columns; j++) 46 { 47 var index = (i * columns) + j; 48 49 // XY平面上に縦にrows個、横にcolumn個並ぶように配置する 50 var position = new Vector3((j - ((columns - 1) * 0.5f)) * 2.0f, (i - ((rows - 1) * 0.5f)) * 2.0f, 0.0f); 51 52 // それぞれの正方形の回転を決める 53 // さしあたりランダムに少しだけ傾けてみました 54 var randomAngle = Random.Range(-10.0f, 10.0f); 55 var randomDirection = Random.insideUnitCircle.normalized; 56 var rotation = Quaternion.AngleAxis(randomAngle, randomDirection); 57 58 positions[index] = position; 59 rotations[index] = rotation; 60 } 61 } 62 } 63 64 void Update() 65 { 66 for (var index = 0; index < count; index++) 67 { 68 Graphics.DrawMesh(mesh, positions[index], rotations[index], material, 0); 69 } 70 } 71}
毎フレーム1万回のDrawMeshはけっこうな負荷になると思われます。もしマテリアルがGPUインスタンシングに対応していれば、代わりにDrawMeshInstancedを使うとレンダリングコストを大幅に削減できるかもしれません。
C#
1using System.Collections; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEngine; 5 6public class ExampleClass : MonoBehaviour 7{ 8 Mesh mesh; 9 Matrix4x4[][] matrices; 10 int count; 11 public Material material; 12 public int rows = 100; 13 public int columns = 100; 14 15 private void Start() 16 { 17 mesh = new Mesh(); 18 mesh.vertices = new Vector3[] { 19 new Vector3 (-1f, -1f, 0), 20 new Vector3 (-1f, 1f, 0), 21 new Vector3 (1f , -1f, 0), 22 new Vector3 (1f , 1f, 0), 23 }; 24 25 mesh.uv = new Vector2[] { 26 new Vector2 (0, 0), 27 new Vector2 (0, 1), 28 new Vector2 (1, 0), 29 new Vector2 (1, 1), 30 }; 31 32 mesh.triangles = new int[] { 33 0, 1, 2, 34 1, 3, 2, 35 }; 36 37 mesh.RecalculateNormals(); 38 mesh.RecalculateBounds(); 39 40 // 各インスタンスの姿勢はMatrix4x4として与える 41 count = rows * columns; 42 var flatMatrices = new Matrix4x4[count]; 43 for (var i = 0; i < rows; i++) 44 { 45 for (var j = 0; j < columns; j++) 46 { 47 var index = (i * columns) + j; 48 49 var position = new Vector3((j - ((columns - 1) * 0.5f)) * 2.0f, (i - ((rows - 1) * 0.5f)) * 2.0f, 0.0f); 50 51 var randomAngle = Random.Range(-10.0f, 10.0f); 52 var randomDirection = Random.insideUnitCircle.normalized; 53 var rotation = Quaternion.AngleAxis(randomAngle, randomDirection); 54 55 var scale = Vector3.one; 56 57 flatMatrices[index] = Matrix4x4.TRS(position, rotation, scale); 58 } 59 } 60 61 // 一度に描画できるインスタンスは1023個までなので、あらかじめそれを超えないよう切り分けておく 62 matrices = flatMatrices.Select((m, i) => (m, i / 1023)) 63 .GroupBy(t => t.Item2) 64 .Select(g => g.Select(t => t.Item1).ToArray()).ToArray(); 65 } 66 67 void Update() 68 { 69 foreach (var m in matrices) 70 { 71 Graphics.DrawMeshInstanced(mesh, 0, material, m); 72 } 73 } 74}
#追記
タイル1個ごとに頂点が4個生成されますので、頂点総数は130×130×4=67600個となります。頂点インデックスの形式がデフォルトの16ビット整数ですと65535個までしか扱えず、途切れてしまったものと思われます。
さしあたり、indexFormatをRendering.IndexFormat.UInt32に切り替えてみてはいかがでしょうか?
C#
1 void GenerateMesh() 2 { 3 MeshData data = new MeshData(tiles); 4 mesh = new Mesh(); 5 6 // 頂点インデックスのフォーマットを32ビット整数に変更する 7 mesh.indexFormat = IndexFormat.UInt32; 8 9 mesh.vertices = data.vertices.ToArray(); 10 mesh.triangles = data.triangles.ToArray(); 11 mesh.RecalculateNormals(); 12 mesh.RecalculateBounds(); 13 Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.identity, material, 0); 14 }
リファレンスによると一部の環境では32ビットインデックスをサポートしないそうですので、それらにも対応させたい場合はメッシュを複数個に分割する必要がありそうですね。
投稿2019/04/09 20:36
編集2019/04/09 21:16総合スコア10807
0
とりあえず、自分で書いたコードを載せます。ただ、widthとheightが130以上(?)だと中途半端にしか描画されません。
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class World : MonoBehaviour { 6 7 public int width; 8 public int height; 9 10 public Tile[,] tiles; 11 12 public Material material; 13 14 Mesh mesh; 15 16 // Use this for initialization 17 void Start () { 18 CreateTiles(); 19 GenerateMesh(); 20 } 21 22 // Update is called once per frame 23 void Update () { 24 Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.identity, material, 0); 25 } 26 27 void CreateTiles() 28 { 29 tiles = new Tile[width, height]; 30 31 for(int i = 0; i < width;i++) 32 { 33 for(int j = 0;j < height;j++) 34 { 35 tiles[i, j] = new Tile(Tile.Type.Stone); 36 } 37 } 38 } 39 40 void GenerateMesh() 41 { 42 MeshData data = new MeshData(tiles); 43 mesh = new Mesh(); 44 mesh.vertices = data.vertices.ToArray(); 45 mesh.triangles = data.triangles.ToArray(); 46 mesh.RecalculateNormals(); 47 mesh.RecalculateBounds(); 48 } 49} 50 51
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class MeshData{ 6 7 public List<Vector3> vertices; 8 public List<int> triangles; 9 10 public MeshData(Tile[,] data) 11 { 12 vertices = new List<Vector3>(); 13 triangles = new List<int>(); 14 15 for(int i = 0; i < data.GetLength(0); i++) 16 { 17 for(int j = 0;j < data.GetLength(1); j++) 18 { 19 CreateSquare(data[i, j], i, j); 20 } 21 } 22 } 23 24 void CreateSquare(Tile tile,int x,int y) 25 { 26 vertices.Add(new Vector3(x + 0, y + 0)); 27 vertices.Add(new Vector3(x + 1, y + 0)); 28 vertices.Add(new Vector3(x + 0, y + 1)); 29 vertices.Add(new Vector3(x + 1, y + 1)); 30 31 triangles.Add(vertices.Count - 1); 32 triangles.Add(vertices.Count - 3); 33 triangles.Add(vertices.Count - 4); 34 35 triangles.Add(vertices.Count - 2); 36 triangles.Add(vertices.Count - 1); 37 triangles.Add(vertices.Count - 4); 38 } 39 40} 41
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Tile{ 6 7 public enum Type { Stone } 8 public Type type; 9 10 public Tile(Type type) 11 { 12 this.type = type; 13 } 14}
200×200で描画すると、中途半端にしか描画されません。なぜなのでしょうか? 100×100は普通に描画されます。
投稿2019/04/09 20:28
編集2019/04/09 20:53退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/09 20:41
2019/04/09 21:18
退会済みユーザー
2019/04/09 21:43