Unityでインディゲームを作る!

Unityでのゲーム制作を目指し、それに関わる話題についてのブログ

Project configuration編 Unity eBook "Optimaize Your Mobile Game Performance" を読み解く

Optimize_Your_Mobile_Game_Performance

 Unityが公式に発行しているeBook"Optimize Your Mobile Game Performance"を読み解いていこう!という企画で、今回はプロジェクト設定編です。(前回はProgramming and code architecture編

 この章も短いのでサクッといってしまいましょう!

 

Project configuration

 モバイルのパフォーマンスに影響を与えうる、いくつかのプロジェクト設定があります。

アクセラメーターを無効化するか、周波数を減らそう

 Unityは一秒間に数回、モバイルのアクセラメーターの値を蓄えます。使わない場合はこれを無効化し、あるいはパフォーマンスを良くするために周波数を減らしましょう。

 

必要ないPlayer設定、Quality設定を無効にしよう

 Player設定で、サポートしていないプラットフォームにおいてはAuto Graphics APIを無効化して、無駄なシェーダー変数の生成を防ごう。

 

 もしあなたのゲームがサポートしないのであれば、古いCPUに対するTarget Architectureを無効化しよう。

 

 Quality設定で、必要のないクオリティ・レベルは無効化しよう。

 

必要ない物理演算を無効に

 もし、あなたのゲームが物理を使っていないのなら、Auto SimulationAuto Sync Transformsを無効にしよう。これらは何の恩恵も無しに、ただただアプリケーションを遅くするだけです。

 

正しいフレームレートを選択しよう

 モバイルプロジェクトにおいて、必ずバッテリー残量、廃熱とフレームレートのバランスを取らなければなりません。

 60FPSまで制限を押し上げる代わりに、30FPSでの動作に妥協することを考慮してください、Unityでのモバイル動作のデフォルト設定は30FPSです。

 

 Application.targetFrameRateを使って、動的にフレームレートを調整することが可能です。例えば、ゆったりとした、比較的変化のないシーンにおいて、30FPSで動作させ、ゲームプレイでは高FPS設定を使う、ということも出来ます。

 

大きなヒエラルキーを避けよう

 ヒエラルキーを分割しよう!ヒエラルキー上でネストする必要がないゲームオブジェクトは、親子関係を単純化しよう。

 マルチスレッディングによる、シーン上のTransformの更新は、浅いヒエラルキーの方が処理が速いです。

 

 ヒエラルキーが複雑な場合、必要のないTransformの計算と、ガベージコレクションに対する更なるコストを生み出します。

 

 Transformに対する、最高の実践を学ぶために、ヒエラルキーの最適化Uniteでの講演を確認してください。

 

二度ではなく、一度にTransformする

 Transformを移動させる時は一度に位置と回転を更新するために、Transform.SetPositionAndRotationを使おう。

player.transform.SetPositionAndRotation(targetPosition, targetRotation);

 これによって、Transformを二度変更することによるオーバーヘッドを避けることが出来ます。

 

 ランタイム中にゲームオブジェクトをInstantiateする必要がある場合、Instantiateメソッド内で、位置や親子関係、回転を指定するのがシンプルな最適化です。

Instantiate(prefab, parent);

Instantiate(prefab, parent, position, rotation);

 

Vsyncが有効であると想定しよう

 モバイル・プラットフォームでは、半フレームはレンダリングしません。エディターのQuality設定でVsync(垂直同期)を無効にしていたとしても、ハードウェア上ではVsyncは有効です。

 もし、GPUが十分、高速に更新できない場合、あなたのFPSは影響があるほどに減少し、現在のフレームは保たれるでしょう。

 


 

 というわけで、プロジェクト設定編でした。短いながらも、直ぐにでも実践できる内容が多く含まれており、大変タメになりました。

 

 次回はAssets編です。各種アセットをどう取り扱うか、という部分で細かいながらも重要な部分だと思うので、気合入れてやっていきたいと思います!

 

フリーゲーム投稿サイト Unity Roomに初めて投稿してみた!

SceneLoadTestGame

 とりあえず何か、まず発表してみようと思い、フリーゲーム投稿サイトである、Unity Roomに投稿してみることにしました。

 Scene Managementをテストするために作ってみたテスト用のゲームです。FPSではありますが弾は打てず、ただ移動とジャンプをしながら、ハートを集めるだけのぎりぎりゲームと呼べるかどうかというものですが、とりあえず投稿してみます!

 

 基本的には、いわゆる一般的なFPSの操作性で、ハートを50個集めるのが目的です。落下したら、最初からやり直しになります。初見でも、5分程度でクリアできるかと思いますので、よろしければぜひ遊んでみてください!

 

苦労話

 以後、今回投稿してみるまでにぶち当たった苦労話など。 

 

 プラットフォームはWebGLで、いろいろこれが厄介というか、エディターでは大丈夫なのに、ビルドしてブラウザ上でプレイすると上手くいかなかったりと、なかなか大変でした。

 Unity RoomではGzipという圧縮形式でビルドしたWebGLのみを受け付けています。一応これはデフォルトで設定されているので、まぁ大丈夫だと思います。

 

 また、WebGL PublisherというパッケージでUnity PlayというUnity公式のゲーム投稿サイトにエディターから直接投稿できるのですが、これで投稿してもロードが90%で止まって上手くゲームを始められない、という問題に遭遇したりで大変ムカつきました。(いろいろ調べてますが、多くの人がこの現象にぶつかっているようです)

 

 あと、先述したように、このマイクロゲームは元々シーンのローディングを試してみるために作ったものでした。Additiveモードのシーン・ロードで追加的にシーンを読み込んでいく、ということを試しています。

 ただし、Active Sceneという概念が存在し、複数シーンを同時に存在している場合には、どれかのシーンにこれを指定しなければいけず、これが切り替わると、Lightingの設定が切り替わります。

 しかし、シーンにLighting dataが設定されていないと、照明がおかしくなる、という現象が起きたりしました。

 

 ここらへんはWebGLだけの問題ではないので、後日にLightingの設定問題として別個記事を書きたいと思います。

 

 という具合に、WebGLに関してはいろいろあるのですが、やはりブラウザ上で自分のゲームを遊んでもらえる、というのは絶対良いことなので、きっちり押さえて、今後どんどんいろんなゲームを発表していきたいな、と思いました。

 

Programming and code architecture編 Unity eBook "Optimaize Your Mobile Game Performance" を読み解く

Optimize_Your_Mobile_Game_Performance

 Unityが無料で発行しているeBook"Optimaize Your Mobile Game Performance"を読み解いていこう!という企画で、今回はプログラミングとコード設計に関する章です。

(前回はAdaptive Performance編

 Unityのコアの部分はC++で書かれていますが、スクリプト言語としてはC#が採用されています。近代的なオブジェクト指向言語であるC#は実際、扱いやすい言語ですが、Unity上ではそのコーディングに注意が必要な部分もあるので、今回の章で学べる知識はぜひ活かしていきたいです。

 

Programming and code architecture

 UnityのPlayer Loopには、Unityのコア部分と相互にやり取りする関数が含まれています。この木のような構造は、初期化とフレーム毎のアップデートを扱う複数のシステムによって構成されています。

 あなたの全てのスクリプト(※つまりC#スクリプト)は、このゲームプレイを生み出すPlayer Loopに依ることとなります。

 

 Profiler上のPlayer Loopの箇所で、あなたのプロジェクト上の全てのスクリプトを確認できるでしょう。これから紹介する、豆知識やトリックでスクリプトを最適化することが出来ます。

(※以後、様々な豆知識やテクニックが説明されていきます)

UnityのPlayer Loopを理解しよう

 Unityのフレーム・ループの実行順を理解しよう。Unityはいくつかのイベント関数をあらかじめ決まった順に実行します。Awake, Start, Updateの違いを理解しなければいけません。

Order Of Execution Of Event Function(イベント関数の実行順序)

 

毎フレーム実行されるコードを最小化しよう

 そのコードが毎フレーム実行される必要があるのかを考えよう。必要のないコードはUpdate, FixedUpdate, LateUpdateの外に出そう。

 Time.FrameCountなどを使ってNフレーム毎に処理する、ということも出来ます。

 

StartやAwake関数に重い処理を置かない

 シーンが読み込まれた時、Awake, OnEnable, Start関数がそれぞれのゲームオブジェクト毎に実行されます。ここに重い処理を置くと、必要以上にローディング時間が掛かってしまう場合があります。

 

空のUnityイベントを避けよう

 空のMonoBehavioursでもリソースを消費します。なので、空のStart, Updateは削除しよう。

 プリプロセッサを使えば、ビルドを汚さず、エディター上においてのみ、Update関数を使う、ということも出来ます。

#if UNITY_EDITOR

void Update(){

}

#endif

 

Debug.Log文を削除しよう

Update, LateUpdate, FixedUpdate中のDebug.Logは、パフォーマンスを低下させます。ビルド前には取り除くようにしましょう。

 Conditional Attributeを使うとより簡単にこれを行うことが出来ます。ログ出力のためのクラスを作成し、[System.Diagnostics.Conditional("ENABLE.LOG")]

アトリビュートを付けて、プレイヤー設定(Player Settings)でENABLE.LOGの定義シンボルをオフにすることで、コード全体からログ出力部を削除する、ということも可能です。

 

文字列ではなくてハッシュ値を使おう

 unityではアニメーター、マテリアル、シェーダーのプロパティを内部では文字列として扱っていません。処理スピードのために、プロパティは全て、ID(整数値)に変換し、それで実際のプロパティを指定します。

 文字列を使うと、結局内部ではハッシュ値への変換を行い、ハッシュ値を使う関数を呼び出しているので無駄です。

 アニメーターではAnimator.StringToHashを、マテリアルやシェーダーではShader.PropertyToIDを使おう。(※スタート関数でこの処理を行い、変数に保存しておくのが安定だと思います)

 

正しいデータ構造を選ぶ

 データ構造についてのあなたの選択は、フレーム毎に何千回も処理が反復されるにつれて、累積的な影響を与え得る。

 リストや配列、ディクショナリを使うことに対して、注意を払っていますか?C#において正しいコレクションを選ぶのに、一般ガイドとなる・・・

を抑えておきましょう。

 

ランタイム中にコンポーネントを追加するのを避けよう

 AddComponent関数をランタイム中に呼び出すのは幾分かのコストが掛かります。ランタイム中にコンポーネントを追加する際は毎回、Unityは複製や他に必要になるコンポーネントをチェックしなければならないからです。

 プレハブをInstantiateするのは、既に必要なコンポーネントが準備、装着されているため、一般的には負荷が少なくて済みます。

 

ゲームオブジェクトやコンポーネントをキャッシュしよう

 GameObject.FindGetComponent関数はコストが高いので、Update関数で呼び出すのは避けたいです。代わりにStart関数でそれらを実行し、結果をキャッシュしましょう。(※キャッシュ"Cache"とは、一度読み込んだデータを直ぐに再利用できるように手元に置いておく、というような意味です)

 そうすれば、一回だけの実行で済み、余計な呼び出しをせずにUpdate関数内でも何回でも使えます。

 

オブジェクト・プールを利用しよう

 InstantiateやDestroyはガベージを生み、ガベージ・コレクションによるスパイクを発生させます。これは通常、プロセスを遅くします。これらの関数の代わりに、良く使うゲームオブジェクト(例えば、銃の弾やビーム)に対して、再利用や再生できるようにあらかじめ割り当てたオブジェクトのプールを使います。

 CPUのスパイクがゲームに影響を与えないポイントで、ゲームオブジェクト群のインスタンスを作っておいて、そのプールをコレクションとして追跡、管理します。

 ゲームプレイ中は単純に、必要になったら利用可能なゲームオブジェクトを有効にして、Destroyする代わりにそのゲームオブジェクトを無効にしてプールに戻します。

 

 これはプロジェクト内部のメモリ割り当てを減らし、ガベージコレクションによる問題を防止することが可能になります。

・Unityにおける、簡潔なオブジェクト・プーリング・システムについて

 

ScriptableObjectを使おう

 MonoBehaviourの代わりに、不変なデータや設定はScriptableObjectsに保存しよう。ScriptableObjectsは一回だけセットアップすればいい、プロジェクト内部に実存するアセットです。ゲームオブジェクトに直接アタッチすることは出来ません。

 値や設定を保存するのに、ScriptableObjects内にフィールドを作成し、それをMonoBehavioursが参照します。

 

 ScriptableObjectsからのフィールドを使うことで、MonoBehaviourによるゲームオブジェクトを生成する際に、余計なデータの複製を防ぐことが出来ます。

 

 ScriptableObjectsがどのようにあなたのプロジェクトに活かせるかについて、

を視聴しましょう。ScriptableObjectsについてのドキュメントもあります。

 


 

 以上です!ほぼ丸々翻訳になってしまいました・・・。捨てるところがほとんどない章だったので、しょうがないですが!実際、今回取り上げられた各テクニックは直ぐにでも使うべきものばかりだっだと思うので、活かしていきたいです。

 

 ScriptableObjectsに関しては、いずれ単独テーマとしてとりあげて、みっちりやりたいと考えています。

 

次回はProject configuration編です。

 

MadeWithUnity探検隊! 色を取り戻す旅へ "GRIS"

GRIS_Singing

 微細なイラストとエモーショナルな音楽の融合。今回のMadeWithUnity探検隊はGRISについてのレビューをまとめます。

 ここ最近扱ったMadeWithUnity作品の中では、良くも悪くも語る所がないというか、世界観と雰囲気が全てのゲームだと言えるので、スクショやプレイ動画を見て、興味が出たら遊ぶくらいで良いと思います。

 

 三時間ほどでクリアしました。絵本と音楽アルバムが一緒になったような作品であり、一気にやってしまうのがいいだろうと思ったので、初見で一気にやりきりました。

GRIS_CollectOrb

光る珠を集めよう

 ジャンル自体は2Dプラットフォームでアクションゲームですが、先述したようにアクション自体よりもイラストや音楽、世界観を楽しむ作品と言えると思います。

 基本的には敵キャラというものは出てこず、プレイヤーがダメージを受けて体力が減るというシステムはありませんし、ゲームオーバーもないです。

 

 アクションの難度も高くなく、やはりアクションそのものを楽しむゲームではないと個人的には思いましたが、つまりはアクションが苦手な人でも出来るレベルデザインということです。構造的にもリニア進行なので、詰まることもほぼ無いかと思います。

 絵的デザインを優先した結果、少し分かりにくい場面があったりもしましたが、全体としてストレスなく遊べる設計になっていると思います。

GRIS_Desert

 色が失われた世界に放り出された主人公が、最初はモノクロの砂漠を駆け抜け、様々な冒険を繰り広げることになります。

 単純なジャンプアクションだけでなく、いくつかの特殊能力もあり、尖った部分はないもののアクションゲームとして無味乾燥なゲームではなかったのが良かったです。

GRIS_RedColorRetrieve

 モノクロの世界に色を取り戻す、という王道ながら分かりやすい目標が良いし、絵的にも世界がどんどん広がっていくのが良かったです。やっぱグラフィックによる感情移入は大事ですね。

GRIS_Tower

 個人的には、上空の鉄骨?ステージの空気感が良かったです。でも落下死が無いのでそこは非常に優しいゲームですね。

GRIS_WaterPalace

 各色をテーマにしたエリアを微細なタッチの絵で表現しており、繰り返しますが、そこがこのゲームの一番の魅力だと思います。こうやってゲーム画面のスクショを並べると、やっぱ絵が良いですね。

 

 正直、もう一回やるかと聞かれたら自分はやらないのですが、三時間でサクッと遊べる雰囲気ゲーとしては順当に良くできた佳作ゲームでした。

 

Adaptive Performance編 Unity eBook "Optimaize Your Mobile Game Performance" を読み解く

Optimize_Your_Mobile_Game_Performance

 今回はOptimize Your Mobile Game PerformanceのAdaptive Perfomance編です。この章は短いので、サクっと行ってしまいましょう。Adaptive PerformanceはUnityパッケージとして準備されており、パッケージ・マネージャーからインストールできます。

Adaptive-Performance_PackageManager

 恥ずかしながら、自分はまだちゃんとAdaptive Performanceを使ったことがないので、これを機に勉強して行けたらなと思います。では、以降は本文の簡潔な翻訳、まとめになります。

 

Adaptive Performance

 UnityとSamsungによるAdaptive Performanceで、モバイル・デバイスの温度や電力状態をモニタリングすることができ、適切に対応できる準備を整えます。Adaptive Performanceによって、開発者はグラフィックの質を保ちつつ、制御された方法でゲームのパフォーマンスを向上させることが出来ます。

 

 アプリケーションの詳細な調整のためのAPIを利用できる一方で、このパッケージは自動モードも提供してくれます。自動モードでは、いくつかのカギとなる指標に基づき、Adaptive Performanceがゲームの設定を決定してくれます。

 

・以前のフレームから望まれるフレームレート

・デバイスの温度

・発熱イベントに対するデバイスの密接度(?)

・CPUが重いか、GPUが重いか

 

 これらの4つの指標でデバイスの状態を判定し、Adaptive Performanceはボトルネックを減らすために設定を(自動で)調整します。これはインデクサーと呼ばれる、デバイスの状態を示す整数値が提供されることによって行われます。

 

 よりAdaptive Performanceについて学びたい場合は、パッケージマネージャーのページからサンプルをインストールできます。

 各サンプルはそれぞれ特定の尺度に対して、反応します。これにより、様々な尺度があなたのゲームにどのような影響を与えるかを確認することが出来ます。

 

 Adpative Performance の各種設定やAPIとどう連携するかについて詳しく学ぶのにユーザーガイドも見ることをお勧めします。

 


 

 というわけで、Adaptive Performanceについての章でした。モバイルゲームを作る際には絶対に使うべきツールだと思うので、そろそろ使い方を覚えておきたいです。そうなると、やっぱ覚えること多いですね!

 

次回はProgramming and code architecture編です!