KENTEM TechBlog

建設業のDXを実現するKENTEMの技術ブログです。

Unityで動的メッシュ作成の落とし穴

開発部エンジニアのY.A.です。
今日はUnityを使って動的に3Dモデルを作成していた際にはまった点をお話ししたいと思います。

はじめに

UnityではMeshクラスを用いて、任意の3Dモデルを作成できます。
具体的な方法は省略しますが、以下のような手順で作成します。

  1. 頂点一覧を渡す
  2. 頂点をどのような順番でつなぐかの一覧を作成する
  3. Meshクラスに渡す

今日のゴール

私が目指しているゴールは以下のような3Dモデルを表示できるようにすることです。
色も鮮やかでとても見やすいですね。
いくつかのモデルを動的に読み込みましたが、テストの中でこのファイルだけうまく取り込めませんでした。

成功例

現実

これが、実行時の現実です。
メッシュが左右に広がり、3Dモデルが完全に崩れています。

失敗例

原因と対応方法

色々と調査していて、頂点数が65535を閾値として描画が崩れていることが分かりました。
最初はシェーダーやレンダラーに問題があると思っていたのですが、とても身近に設定がありました。 65535を超える頂点数はデフォルトでは保持できないんですね。

参考記事

以下の記事でシンプルな対応ができるようになりました。
65535が閾値とわかったときは、65535でモデル分割するべきか悩んでいたので助かりました! inoookov.hatenablog.com

対応方法

最終的にはMeshクラス作成時の処理を以下のようにすることで、動的生成時の頂点数問題に対応しました。
IndexFormat.UInt32を常に設定してもいいのですが、メモリの確保サイズが2倍異なるとのことだったので、可変にしました。

var mesh = new Mesh();

//▼頂点数に応じてindexFormatを変更
if (vertices.Count > ushort.MaxValue)
    mesh.indexFormat = IndexFormat.UInt32;//頂点数:4294967295
else
    mesh.indexFormat = IndexFormat.UInt16;//頂点数:65535

mesh.name = lay.Layer.Name;
mesh.vertices = vertices.ToArray();//頂点の設定
mesh.normals = normals.ToArray();//法線ベクトルの設定
mesh.colors32 = colors.ToArray();//頂点色の設定
mesh.SetIndices(triangles, MeshTopology.Triangles, 0);//頂点インデックスの設定
mesh.Optimize();

まとめ

Unityは座標値もFloatだったりと、デフォルトで桁数が少なめに定義されているので、もっと早く気づくべきでした。
コードを書いた後に、「頂点の一覧はこちらから渡しているのだからMeshクラスでいい感じにやってくれないかなぁ」と心の中で文句を言いながら、 いい感じに描画できたモデルをまじまじと眺めています。
3Dの描画は最初が大変ですが、描画ができてしまうととても楽しいですよね。

今後はマテリアルを調整等してもっときれいな描画になるように心がけていきたいです!

おわりに

KENTEMでは、様々な拠点でエンジニアを大募集しています! 建設×ITにご興味頂いた方は、是非下記のリンクからご応募ください。 recruit.kentem.jp career.kentem.jp