Help us understand the problem. What is going on with this article?

Unityのシーン上でアクティブな3Dモデルの頂点とポリゴンを数えてみる

More than 3 years have passed since last update.

概要

ゲームを快適にプレイするためにはFPSを保つ必要があります。(特に、VR系コンテンツは最低でも60fpsは出したいところ)
FPSが落ちる要因は様々あって一概にこれ!ということは難しいですが、可能性の一つとして3Dモデルの出しすぎや1つのモデルのポリゴン数が多すぎ等が挙げられます。
ということで、シーン上でActiveになっている3Dモデルの頂点とポリゴンを数えてみる方法になります。

Unityのバージョン

5.4.2f1

アクティブな3Dモデルの頂点とポリゴンを数える

サンプルコード

PolygonCounter.cs
using UnityEngine;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class PolygonCounter : MonoBehaviour {

    int vertices;
    int polygons;

    [SerializeField]
    int minFps = 60;

    int frameCount = 0;
    float nextTime = 0.0f;

    void Start () {
        nextTime = Time.time + 1;
    }

    void Update () {

        frameCount++;

        // 1秒ごとにFPS検証
        if (Time.time >= nextTime) {
            // Debug.LogFormat ("{0}fps", frameCount);
            if (frameCount < minFps) PolygonCount (frameCount);

            frameCount = 0;
            nextTime += 1f;
        }

    }

    [ContextMenu("CountStart")]
    void PolygonCount(int fps = -1){

        vertices = 0;
        polygons = 0;
        foreach (GameObject obj in UnityEngine.Object.FindObjectsOfType(typeof(GameObject))) {

            if (obj.activeInHierarchy) {

                SkinnedMeshRenderer skin = obj.GetComponent<SkinnedMeshRenderer> ();

                if (skin != null) {
                    int vert = skin.sharedMesh.vertices.Length;
                    vertices += vert;

                    int polygon = skin.sharedMesh.triangles.Length / 3;
                    polygons += polygon;
                }

                MeshFilter mesh = obj.GetComponent<MeshFilter> ();

                if (mesh != null) {
                    int vert = mesh.sharedMesh.vertices.Length;
                    vertices += vert;

                    int polygon = mesh.sharedMesh.triangles.Length / 3;
                    polygons += polygon;
                }

            }
        }
        Debug.LogFormat ("Vertices(verts) : {0} , Polygons(Tris) : {1} , FPS : {2} " ,
            vertices , polygons, fps);  

    }

#if UNITY_EDITOR

    [CustomEditor(typeof(PolygonCounter))]
    public class CountStartEditor : Editor {

        PolygonCounter polygonCounter;

        void OnEnable(){
            polygonCounter = target as PolygonCounter;
        }

        public override void OnInspectorGUI ()
        {
            base.OnInspectorGUI ();

            if (GUILayout.Button("カウント開始")){
                polygonCounter.PolygonCount ();
            }
        }

    }

#endif

}

使い方

  • 適当なGameObjectにアタッチしてください。
  • インスペクター上で確認したい場合は、「カウント開始」を押してください(何かの不具合でボタンが表示されない場合は、歯車アイコンから「CountStart」を押してください)
  • ゲームプレイ中に確認したい場合は、minFpsの値を設定してください。FPSがminFpsを下回るとカウントを開始します。
  • コンソールログに、シーン上でアクティブな3Dモデルの頂点とポリゴン数が表示されます。

基礎クラス(PolygonCounter)

  • FPSは1秒間に実行したフレームをカウントしています。
  • 設定したFPSを下回るときに、今回のカウンター処理を呼び出しています。
  • シーン上でアクティブなゲームオブジェクトを全検索します。
  • その中でSkinnedMeshRendererか、MeshFilterをコンポーネントとして持っている場合は頂点数とポリゴン数を加算してます。(頂点数とポリゴン数はメッシュのインスペクターに表示される内容です(下記画像を参照))
  • 最終的にデバッグログとして出力します。

mesh_inspector.png

拡張クラス(CountStartEditor)

  • 基礎クラスのメソッドを呼ぶために、有効時に基礎クラスを設定
  • インスペクターを拡張して、ボタンを配置(押されたらメソッド呼ぶ)

補足

  • あくまでデバッグを目的にしているので、デバッグ時以外は外しておいた方が良いです。(そもそも、シーン上の3Dモデルを全検索する負荷が高そうですし)
  • この記事のサンプルコードについては、「【Unity】3Dオブジェクトのポリゴン数を表示させる」を参考にさせてもらいました。
  • バグだったり、こうした方がスマートなどありましたら、ご指摘ください。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away