Unityでメッシュを生成する[1]

長い;前置き

メッシュについて

言うまでもないことですが、3DCGという概念は頂点・頂点をつないだ面・面をまとめたメッシュによって構成されています。 正確にはもっといろいろ(カメラとか質感とかライティングとか)ありますが、そういう難しいことは私にはわかりません。

とりあえず私たちの肉体にあたる部分はコンピュータ上ではそういった頂点とかいうやつの集合と連結によって作られているそうです。 そしてそれを「メッシュ」と呼ぶそうです。

Unity上でのメッシュ

Unity上でメッシュに触ることはほとんどありません。 何か物体を置きたいのなら、もともと用意されているオブジェクトを使うか、FBXなどのモデルデータを読み込むのが常です。 これは非常に優れた技術であり、私が大学時代に経験したような「さあDirect Xを使ってウィンドウを生成して描画領域をクリアしカメラの位置を決定したらメッシュを規定し投影変換で表示してみよう」などとやらなくていいわけです。もう二度とやりたくない。

――ちょっと本音が出ましたが話を戻すと、つまりそういった非人道的な、もとい泥臭い、非常に大変な処理はUnityがやってくれているわけですね。

いつもは。

メッシュ触ってみたい

とはいえ、Unityを使っていれば一切メッシュに触れないのか? というとそういうわけでもありません。 アセットストアなどを見ていてもわかるように、結構メッシュをゴリゴリ動かして何か動かす処理を作っている人は少なくありません。 なんと驚くことにUnity上でモデリグンできるアセットもあるらしいです(なんと無料) 他にも、例えばシェーダーやボーンを用いないで揺れものや流体なんかを動かそうと思うと、メッシュをいじる必要があります。

まあ色々とそういった先行事例がありますが、なんというか、まあ、触れるなら触りたくない? という気持ちになりませんか。なりますよね。私はなりました。 ということで、Unity上でスクリプトから直接メッシュをあれこれする何かを作ってみたいと思います。

メッシュを生成する

メッシュとは

メッシュは先ほども書いたように頂点の集合とその連結です。 具体的にはUnity上では

Mesh -- メッシュ
Mesh.vertices -- メッシュを構成する頂点群
Mesh.triangles -- メッシュを構成する三角面群

のようにデータが作られています

vertices

頂点群です。 Vector3の配列として定義されています。

triangles

三角面群です。 intの配列として規定されていて、面数×3個値が保持されます。 verticesのindexを連続して代入することでその3個ずつを1面として認識します。

vertices = new Vector3[] {
    (1, 1, 0),
    (1, -1, 0),
    (-1, 1, 0),
    (-1, -1, 0)
}
triangles = new int[] {0, 1, 2, 2, 1, 3};

詳しくは メッシュ - Unity マニュアル このあたりを読んでいただけると私の説明よりわかりやすく詳細に書いてあるかと思います。

実際に何かを生成する

上記の例をもとに実際にこれを生成してみましょう。

適当にスクリプトを作って以下のコードを貼り付けてみてください。

 [SerializeField]
    Material material;

    // Use this for initialization
    void Start()
    {
        GameObject obj = new GameObject();
        MeshFilter filter = obj.AddComponent<MeshFilter>();
        MeshRenderer renderer = obj.AddComponent<MeshRenderer>();
        MeshCollider collider = obj.AddComponent<MeshCollider>();
        Vector3[] vertices;

        vertices = new Vector3[] {
            new Vector3(1, 1, 0),
            new Vector3(1, -1, 0),
            new Vector3(-1, 1, 0),
            new Vector3(-1, -1, 0)
        };
        int[] triangles = new int[] { 0, 1, 2, 2, 1, 3 };

        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;

        filter.sharedMesh = mesh;
        collider.sharedMesh = mesh;
        renderer.material = material;
    }

これをなんでもいいので適当なオブジェクトにアタッチして、マテリアルを指定してゲームを実行すると

f:id:mtwand:20180330192711p:plain

はい。こんなものが現れたかと思います。 おめでとうございます! これで私たちはUnity上でメッシュを生成することに成功しました!

今日から「Unity上でメッシュ生成できる」と豪語していきましょう。いえぃ。

…さて、今だれか面白い冗談だと思いましたね。そうですね。 実はまだやらなければいけないことがいくつかあります。

そのあたりはまた今度にしましょう。 次回上記コードの解説も書くだけ書いてみたいと思います。