いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

Unityでスクリプトを使って線分を描く(3)(初心者向け)

 3回目です。前回、以下のようにすれば何度コールしてもエラーを出さずに線分を描画できるということを明らかにしました。が、このままではまずいということが分かりました。

        //1本目
        GameObject g = new GameObject();
        var rd = g.AddComponent<LineRenderer>();
        var pos = new Vector3[]{
            new Vector3(1f, 0f, 20f),
            new Vector3(10f, 10f, 10f),
        };
        rd.startWidth = 1f;//線分の太さ
        rd.endWidth = 1f;
        rd.positionCount = pos.Length;//与えた点の数
        rd.SetPositions(pos);

        //2本目
        GameObject go = new GameObject();
        var rd1 = go.AddComponent<LineRenderer>();
        var pos1 = new Vector3[]{
            new Vector3(-5f, 0f, 20f),
            new Vector3(-10f, 10f, 10f),
        };
        rd1.startWidth = 1f;//線分の太さ
        rd1.endWidth = 1f;
        rd1.positionCount = pos1.Length;//与えた点の数
        rd1.SetPositions(pos1);
    }

 確かに描画はうまくいくのですが、ゲームのステージが進むにつれてFPSが下がり、10分も続けていると15を切るようになってしまいます。ぼくは Start() ルーチンに次のコードを入れています。
Application.targetFrameRate = 40;
フレームレートを抑えてくれるそうです。最初はそのくらいのFPSなのです。
(追記:2021年5月8日
PCはこれでコントロールできましたが、実機(スマホ)ではうまくいきませんでした。QualitySettings.vSyncCount の値にもよるとのこと。しかしそれでもうまくいっていません)

 実は、最初に挙げたコードには書いたときから気になっていた点があります。new GameObject() のたびにゲームオブジェクトが生成されて、それは多分削除されずに残るんだろうけれど、それでいいのかな……と思っていました。ことによるとUnityが定期的に自動で削除してくれているのかも、みたいな期待もありました。これが影響してFPSが下がるのか?
 そこで、試してみました。GameObject は関数内で定義するのではなく次のようにクラスの変数とします。

    GameObject go1 = null;
    GameObject go2 = null;

そして、線分の描画前に次を実行するのです。

        if (go1 != null) { Destroy(go1); }
        if (go2 != null) { Destroy(go2); }

もちろん変数名が変わったので描画のコードも適切に変更します。次のようにします。

        //ゲームオブジェクトを削除
        if (go1 != null) { Destroy(go1); }
        if (go2 != null) { Destroy(go2); }

        //1本目
        go1 = new GameObject();
        var rd = go1.AddComponent<LineRenderer>();
        var pos = new Vector3[]{
            new Vector3(1f, 0f, 20f),
            new Vector3(10f, 10f, 10f),
        };
        rd.startWidth = 1f;//線分の太さ
        rd.endWidth = 1f;
        rd.positionCount = pos.Length;//与えた点の数
        rd.SetPositions(pos);

        //2本目
        go2 = new GameObject();
        var rd1 = go2.AddComponent<LineRenderer>();
        var pos1 = new Vector3[]{
            new Vector3(-5f, 0f, 20f),
            new Vector3(-10f, 10f, 10f),
        };
        rd1.startWidth = 1f;//線分の太さ
        rd1.endWidth = 1f;
        rd1.positionCount = pos1.Length;//与えた点の数
        rd1.SetPositions(pos1);
    }

 こうすると、FPSは下がりません。単純にこれだけが原因なのかは不明ですが、どちらにせよ不要なオブジェクトは削除した方がいいに決まっているのでこうしています。10分、20分と実行し続けていてもFPSは40位を保っています。

 ……というわけで線分の描画についてはここまで。こうしてブログにも残したし、いずれ別のアプリ開発でも役に立つことでしょう。ブログで「××の備忘録」みたいに説明している人を結構見かけます。本当にその通りで、ぼくも自分でブログに載せたコードをコピーして再利用しています。