夕方ゲーム制作

プログラミング初心者がUnityでゲームを作る日記

Unity製アプリが遅いので軽量化した

 Unityで製作中のゲームアプリが、実機で動かすととにかく重かったので、何とかまともに動くまでに軽くしました。

 

 次にアプリを作るときに同じ罠に嵌らぬよう、やったことをここにメモしておきます。

 

 因みに自分はUnity、プログラミングともにずぶの素人なので技術的に見るべき所は無いと思いますが、まぁ一応書いときます。

 

 

最初の状態

 android実機でアプリを動かしてみると、だいたい15~25fpsといった感じで、まともな操作も覚束ないといった紙芝居状態でした。

 

 自分の超安物の型落ちオンボロスマホにはやはり荷が重いのかとも思いましたが、ドット絵調のちっさいテクスチャでここまで遅いのはやっぱりおかしいだろうと調べてみました。

 

 

 

やったこと

 

Update()を呼ばないようにした

 Profilerを見ていると、敵キャラクタが沢山出てきたとき、それぞれのインスタンスのUpdate()を呼び出しているところが結構時間を食っていることが分かりました。一個一個は小さい時間ですが、オブジェクト数が多くなってくると割と無視できないみたいです。

 

 そこで、Update()は誰か代表のクラスが受け取って、他のクラス達にそれを通知する、といった感じにすることでなるべくUpdate()が呼ばれないようにしました。

 

 これを実装した所fpsは3~5くらい改善しました。また、代表で受け取るクラスを工夫すればUpdate()が呼ばれる順番が制御できそうで、これは結構でかいおまけ効果な気がします。

 

 

isStaticを使った

 自分のゲームには、ブロック状のオブジェクトがたくさん出てくるのですが、これを一つ一つ描画してるのがまずいんじゃね?と思ったので調べた所、動かないオブジェクトならgameObject.isStatic=true;にすると一気に描画ができる、みたいな情報が見つかりました。

 

 これをやったところ、fpsは若干改善した、気がします。正直あまり目に見える変化は無かったような・・・。しかし簡単に実装できたし、やらないよりはマシと思います。

 

 

重い処理をキャッシュした

 Unityの軽量化について調べていると、色んな所でFindとGetComponentは重いぞ、という情報が目に付きました。どうやら毎フレームGetComponentするようなのは論外みたい。普通にやってました。

 

 解決方法として、FindやGetComponentの返り値を仕舞っておく変数を用意して、それを後生大事に使い回すのが良いらしい、そしてこれをキャッシュする、と言うらしい。というのが分かりました。こういう単語を知ってれば検索の手間も省けるんでしょうね・・・。

 

 実際やってみました。でもこれもなんか効果がいまいち分かりづらい。スクリプトを書き換えるのにかなり骨が折れたので、これだけ書き換えればfps1000くらい行くんじゃないかと勝手な期待をしすぎたのがアレだったのかも知れませんが。

 

 

SetActiveを使った

 改良前はUIの表示/非表示を切り替える方法が分からなかったので、Imageのアルファを0か1にして出したり消したりしていました。しかしこれはアルファが0でもガッツリ描画処理が動いていて、しかも半透明扱いでゲロ重い処理のようでした。

 

 それならUIをカメラの外に出せば描画処理が動かないのではと重い、非表示にするときにpositionのx座標を1億くらいにして遠くにぶっ飛ばすようにしてみましたが、大した効果はありませんでした。というかこれどう考えても正攻法じゃない・・・。

 

 そこで表示/非表示を切り替える処理を調べた所、SetActive(bool)という、普通にGameObjectの有効化と無効化ができるやつが見つかりました。もうメソッド名からしてハナからこれ使っとけって感じのやつですね。なんで見落としてたんだ。

 

 早速スクリプトを書き換えると、fpsが劇的に改善し、大体45~60くらいは出るようになりました。これだけ出てれば十分ですね。

 というわけで、Profilerとにらめっこしつつ色々やりましたが結局こんなしょうもないやつが主犯でした。無知って恐ろしい。

 

まとめ

 

・オブジェクトの表示/非表示切り替えには、アルファの変更ではなくSetActive(bool)を使う。アルファを0にしても普通に描画処理が動くのでめっちゃ重い。

 

・個々のオブジェクトでUpdate()を呼ぶのは控える。代表者がUpdate()を受け取って他に知らせる仕組みにする。

 

・FindやGetComponentは返り値をとっといて延々と使い回す。毎フレーム呼ばない。

 

・地形とかの動かないオブジェクトはisStatic=trueにする。

 

 

結論

これ正攻法じゃないな、と感じたら面倒がらずにGoogle検索するべき。我流はあかん。