質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

0回答

801閲覧

Unity マップの描画 フレームレートが低い

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/08/27 07:58

前提・実現したいこと

マップを描画したときに、フレームレートが低くなってしまうことを改善したい

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Linq; 5 6public class TerrainGenerator : MonoBehaviour 7{ 8 Mesh mesh; 9 Matrix4x4[][] matrices; 10 Matrix4x4[][] matrices2; 11 Matrix4x4[][] matrices3; 12 13 // 頂点カラー受け渡し用のフィールド 14 Matrix4x4[][] vertexColors; 15 Matrix4x4[][] vertexColors2; 16 Matrix4x4[][] vertexColors3; 17 18 // マテリアルへのデータ投入用のMaterialPropertyBlock 19 private MaterialPropertyBlock materialProperties; 20 21 // プロパティアクセス用の識別番号 22 private static readonly int VertexColorsProperty = Shader.PropertyToID("_VertexColors"); 23 24 int count; 25 public Material material; 26 public Material material2; 27 public Material material3; 28 private int rows = 200; 29 private int columns = 200; 30 private int mapWidth = 200; 31 private int mapHeight = 200; 32 private float noiseScale = 50; 33 private bool drawTerrain = true; 34 private bool drawTerrain2 = true; 35 private bool drawTerrain3 = true; 36 37 private int octaves = 5; 38 [Range(0, 1)] 39 private float persistance = 0.5f; 40 private float lacunarity = 2; 41 42 private int seed; 43 private Vector2 offset = Vector2.zero; 44 45 public static List<Vector2> waterPosList = new List<Vector2>(); 46 47 private void Awake() 48 { 49 seed = Random.Range(-999999, 999999); 50 51 this.mesh = new Mesh(); 52 this.mesh.vertices = new Vector3[] { 53 Vector3.zero, 54 new Vector3 (-0.5f, -0.5f, 0), 55 new Vector3 (-0.5f, 0.5f, 0), 56 new Vector3 ( 0.5f, -0.5f, 0), 57 new Vector3 ( 0.5f, 0.5f, 0), 58 }; 59 this.mesh.uv = new Vector2[] 60 { 61 new Vector2(0.5f, 0.5f), 62 new Vector2(0, 0), 63 new Vector2(0, 1), 64 new Vector2(1, 0), 65 new Vector2(1, 1), 66 }; 67 this.mesh.triangles = new int[] { 68 0, 4, 3, // 北 69 0, 2, 4, // 東 70 0, 1, 2, // 南 71 0, 3, 1, // 西 72 }; 73 74 this.mesh.RecalculateNormals(); 75 this.mesh.RecalculateBounds(); 76 77 this.count = this.rows * this.columns; 78 var flatMatrices = new Matrix4x4[this.count]; 79 var flatMatrices2 = new Matrix4x4[this.count]; 80 var flatMatrices3 = new Matrix4x4[this.count]; 81 float[,] noiseMap = global::Noise.GenerateNoiseMap(this.mapWidth, this.mapHeight, this.seed, this.noiseScale, this.octaves, this.persistance, this.lacunarity, this.offset); 82 83 for (var i = 0; i < this.rows; i++) 84 { 85 for (var j = 0; j < this.columns; j++) 86 { 87 var index = (i * this.columns) + j; 88 89 // iとjが逆のようだったので変更 90 float height = noiseMap[j, i]; 91 var position = new Vector2(j, i); 92 93 var rotation = Quaternion.identity; 94 95 var scale = Vector3.one; 96 97 if (height < 0.35f) 98 { 99 flatMatrices[index] = Matrix4x4.TRS(position, rotation, scale); 100 waterPosList.Add(position); 101 } 102 else if (height < 0.45f) 103 { 104 flatMatrices2[index] = Matrix4x4.TRS(position, rotation, scale); 105 } 106 else 107 { 108 flatMatrices3[index] = Matrix4x4.TRS(position, rotation, scale); 109 } 110 } 111 } 112 113 // 当初の通りタイルを配置したあと、ここで各地形レイヤーに 114 // さらに追加の外周タイルを配置する 115 var flatVertexColors = this.AppendOutlineTiles(flatMatrices); 116 var flatVertexColors2 = this.AppendOutlineTiles(flatMatrices2); 117 var flatVertexColors3 = this.AppendOutlineTiles(flatMatrices3); 118 119 // タイルの座標変換行列と同様に、頂点カラー配列も1023個ずつに分割しておく 120 // 結局同じような記述を6回も繰り返すことになってしまったので、この1023個分割操作を 121 // メソッド化してしまうことにした 122 this.matrices = this.GroupBy1023(flatMatrices); 123 this.matrices2 = this.GroupBy1023(flatMatrices2); 124 this.matrices3 = this.GroupBy1023(flatMatrices3); 125 this.vertexColors = this.GroupBy1023(flatVertexColors); 126 this.vertexColors2 = this.GroupBy1023(flatVertexColors2); 127 this.vertexColors3 = this.GroupBy1023(flatVertexColors3); 128 } 129 130 // 配列要素を1023個ずつに分割して返すメソッド 131 T[][] GroupBy1023<T>(IEnumerable<T> source) 132 { 133 return source.Select((m, i) => (m, i / 1023)) 134 .GroupBy(t => t.Item2) 135 .Select(g => g.Select(t => t.Item1).ToArray()).ToArray(); 136 } 137 138 Matrix4x4[] AppendOutlineTiles(Matrix4x4[] flatMatrices) 139 { 140 var allWhite = (new Matrix4x4(Color.white, Color.white, Color.white, Color.white)).transpose; 141 var allClear = allWhite; 142 allClear.SetColumn(3, Vector4.zero); 143 var colors = Enumerable.Repeat(allWhite, this.rows * this.columns).ToArray(); 144 var needsPlaceTile = new bool[this.rows * this.columns]; 145 for (var i = 0; i < this.rows; i++) 146 { 147 for (var j = 0; j < this.columns; j++) 148 { 149 var index = (i * this.columns) + j; 150 var matrix = flatMatrices[index]; 151 if (matrix[0] > 0.0f) 152 { 153 // この位置にすでに配置済みならスキップ 154 continue; 155 } 156 157 var isLeftEdge = j == 0; 158 var isRightEdge = j == (this.columns - 1); 159 var isBottomEdge = i == 0; 160 var isTopEdge = i == (this.rows - 1); 161 var hasN = !isTopEdge && (flatMatrices[index + this.columns][0] > 0.0f); 162 var hasNE = !isTopEdge && !isRightEdge && (flatMatrices[index + 1 + this.columns][0] > 0.0f); 163 var hasE = !isRightEdge && (flatMatrices[index + 1][0] > 0.0f); 164 var hasSE = !isBottomEdge && !isRightEdge && (flatMatrices[index + 1 - this.columns][0] > 0.0f); 165 var hasS = !isBottomEdge && (flatMatrices[index - this.columns][0] > 0.0f); 166 var hasSW = !isBottomEdge && !isLeftEdge && (flatMatrices[index - 1 - this.columns][0] > 0.0f); 167 var hasW = !isLeftEdge && (flatMatrices[index - 1][0] > 0.0f); 168 var hasNW = !isTopEdge && !isLeftEdge && (flatMatrices[index - 1 + this.columns][0] > 0.0f); 169 170 void MakeOpaque(int vertexIndex) 171 { 172 var color = colors[index].GetRow(vertexIndex); 173 color.w = 1.0f; 174 colors[index].SetRow(vertexIndex, color); 175 needsPlaceTile[index] = true; 176 } 177 178 // まず四隅をすべて透明にしておき... 179 colors[index] = allClear; 180 if (hasN || hasNE || hasE) 181 { 182 // 北~東にかけてタイルが配置されているなら右上を不透明に 183 MakeOpaque(1 + (1 << 1)); 184 } 185 if (hasE || hasSE || hasS) 186 { 187 // 東~南にかけてタイルが配置されているなら右下を不透明に 188 MakeOpaque(1 + (0 << 1)); 189 } 190 if (hasS || hasSW || hasW) 191 { 192 // 南~西にかけてタイルが配置されているなら左下を不透明に 193 MakeOpaque(0 + (0 << 1)); 194 } 195 if (hasW || hasNW || hasN) 196 { 197 // 西~北にかけてタイルが配置されているなら左上を不透明に 198 MakeOpaque(0 + (1 << 1)); 199 } 200 } 201 } 202 203 for (var i = 0; i < this.rows; i++) 204 { 205 for (var j = 0; j < this.columns; j++) 206 { 207 var index = (i * this.columns) + j; 208 if (needsPlaceTile[index]) 209 { 210 // 不透明化処理を行った位置に追加のタイルを設置する 211 var position = new Vector3(j, i, 0); 212 var rotation = Quaternion.identity; 213 var scale = Vector3.one; 214 flatMatrices[index] = Matrix4x4.TRS(position, rotation, scale); 215 } 216 } 217 } 218 219 return colors; 220 } 221 222 void Update() 223 { 224 if (this.materialProperties == null) 225 { 226 this.materialProperties = new MaterialPropertyBlock(); 227 } 228 229 void DrawTerrain(Material mat, Matrix4x4[][] mtx, Matrix4x4[][] vCol) 230 { 231 for (var i = 0; i < mtx.Length; i++) 232 { 233 // プロパティブロックに頂点カラーデータを投入し、DrawMeshInstancedの引数として渡す 234 var m = mtx[i]; 235 this.materialProperties.SetMatrixArray(VertexColorsProperty, vCol[i]); 236 Graphics.DrawMeshInstanced(this.mesh, 0, mat, m, m.Length, this.materialProperties); 237 } 238 } 239 240 // デバッグ用に、各地形レイヤーを描画するかどうかをフラグを見て切り替えさせるようにして 241 // 特定の地形レイヤーを単独で描画したりできるようにした 242 // なお、描画順はDrawMeshInstancedを実行した順番とは異なる可能性があるので要注意 243 // デフォルトではmaterial、material2、material3とも3000だと思うが 244 // たとえばmaterial2は3001、たとえばmaterial3は3002にでもしておけば 245 // 意図通りの順序で描画されるはず 246 if (this.drawTerrain) 247 { 248 DrawTerrain(this.material, this.matrices, this.vertexColors); 249 } 250 251 if (this.drawTerrain2) 252 { 253 DrawTerrain(this.material2, this.matrices2, this.vertexColors2); 254 } 255 256 if (this.drawTerrain3) 257 { 258 DrawTerrain(this.material3, this.matrices3, this.vertexColors3); 259 } 260 } 261} 262

試したこと

複数体のオブジェクトに経路探索をさせながら、マップを描画していると、十秒に一度くらいの間隔で、フレームレートが急落し、ゲームがカクカクに見えてしまいます。どのようにすれば、改善できるでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問