はじめに

前の記事からの続きです。

私の4つ目のマイルストーン開発記です。さらにもう一ヶ月で作った成果物をまとめました。今回の一ヶ月は主にゲームのシステムとコンテンツ拡張作業が中心となり、詳細には今回の段階で作ったものはこうです。

  • ゲームシステム
    • 背景オブジェクトの階層化
    • シェーダーグラフ交換による最適化
    • ピンチズームアウトでアクセス可能な設定画面
    • プロシージャルアニメーションを用いたオブジェクトインタラクション
  • 追加されたオブジェクト
    • 背景役割を果たす2種の建物オブジェクト

アーカイブ

settings-test設定画面への進入テスト中に録画

アセット制作

画像アセット

pigeon-diggingpigeon-digging地面をつつく鳩

キーフレーム形式のアニメーションは継続して追加していく予定です。今回は、鳩について地面をつつく動作の実装のためにアニメーションを作りました。アニメーションの分量も短く、何より以前に作ったアセットがあるので、以前のように他の鳩の映像を探して特徴を見つけて真似るといった負担はありませんでした。

前と同様にDigState.csを作って状態パターンと連動する作業をし、おかげで動作も自然に見えます。インタラクションは優先的に鳩を選択した状態で地面をタッチすると発動します。

シェーダーファイル

詳しくは後述しますが、GPUコストの問題があり、使用中の2Dスプライトシェーダーをより軽いものに変更しました。問題は、このシェーダーは影の生成Cast shadow機能がなく、ポストプロセッシングの被写界深度DOF効果が適用されないことです。改善できれば良いですが、シェーダーはまだ慣れていないので、詳しく勉強するか演出上の機能を諦めるかしなければならないようです。

開発過程

カメラスタイルの設定画面実装

settings-activatedピンチズームで設定画面に進入、まだプロトタイプ

設定画面はUIのないすっきりした画面を最大限保存し、少し面白い演出になるよう、別途のUI表示なしでピンチズームでアクセスできるようにしました。ピンチズームは段階的に動作し、一定範囲内では普通のカメラズームインアウトとして動作しますが、一定範囲を超えると振動フィードバックとともに設定画面に進入します。一度アクセスした設定画面からはピンチズームインで出ることができます。

設定画面のUIはカメラのように見えるように作りました。たまに写真を撮りながら、普段POV Street Photographyの動画を見て感じていた感覚をそのまま移したものです。手に取ったスクリーンの中のシーンが自分と被写体の間の膜を突き抜けて、シーンがリアルにつながるような感覚があり、その経験を模倣してみたかったのです。

バッテリーや時間はSystemInfo.batteryLevelDateTime.Nowを使って実際のバッテリー状態と時間を表示するように作り、シャッタースピードと絞り値はそれぞれポストプロセッシングのモーションブラーと被写界深度効果を調整するオプションとして機能させる予定です。

テキストがデフォルトフォントで表示されるなど、まだ完成すべき部分が残っていますが、今まで作られただけでも経験がユニークだと感じられ、ひとまず満足しています。

プロシージャルアニメーションの適用

people-staring-pigeons近くに鳩がいるとときどき見る

以前のマイルストーンを作りながら、プロシージャルアニメーションを使って環境とインタラクションする有機的なアニメーションを作るのを見て本当に素晴らしいと思い、よく覚えておいて今回試してみました。技術的に精巧な条件を設定して実装するものだと思っていましたが、Unityパッケージとして提供されているため思ったより簡単でした。ただしコードで制御するのは思ったより複雑でした。

鳩と違い、人は頭、体、脚などが個別オブジェクトとして独立して分かれており、Animation RiggingパッケージMultiple Aim Constraintコンポーネントを使って、人の頭部オブジェクトが一定距離内で鳩の方を向いて見る機能を試しに実装しました。

public void ChangeSourceObject(GameObject discoveredObject)
{
    WeightedTransformArray sourceObjects = Constraint.data.sourceObjects;
    WeightedTransformArray newSourceObjects = new WeightedTransformArray(sourceObjects.Count);
    
    newSourceObjects[0] = new WeightedTransform();
    WeightedTransform wt = newSourceObjects[0];

    /* ... */

    newSourceObjects[0] = wt;
    
    data.sourceObjects = newSourceObjects;

    Animator.enabled = false;
    rigBuilder.Build();
    Animator.enabled = true;
}

この機能を実装するにはMulti Aim ConstraintコンポーネントのsourceObjectプロパティをシーン内のオブジェクトに交換する必要がありますが、このプロセスに多くの困難があり大変でした。もしプロシージャルアニメーションのsourceObjectをコードで変更したい方がいらっしゃれば、以下を参考にすると役立つでしょう。

  • sourceObjectsのプロパティは読み取り専用(read-only)です。他のローカル変数にデータを定義した後、data.sourceObjectsに新しい値を代入する必要があります。
  • 指定が完了した後は、該当オブジェクトのアニメーターを無効化してからrigBuilderをビルドした後、アニメーションを再有効化する必要があります。
  • あるオブジェクトが他のオブジェクトのsourceObjectとして登録された場合、そのオブジェクトが削除される際に、自身が登録されているsourceObjectプロパティをNoneに変更する必要があります。

公式ドキュメントを調べても解決法を見つけにくい動作やエラーがあって困った状況が多くありましたが、結果的によく作り上げたと思います。実装してみると確かにゲームの雰囲気を柔軟にしてくれる効果があるようです。後日3Dのトイプロジェクトでも作ることになれば、ぜひもっと活用してみたいです。

プロファイラを用いた最適化の試み

profilerUnityプロファイラで測定されるサンプルデータ

私のゲームはおかしなことに、ビルド後40FPSレベルのフレーム維持もできないほど発熱が激しかったです。私のコードが完璧ではなくても、GetComponent()Find()などの重い関数を避け、forforeach、コルーチンなどの反復動作があるコードは無理に実行されないよう気をつけて書くなど基本的な部分は守っていると思っていましたが、明らかに軽いはずの2.5Dプロジェクトにもかかわらずフレームが落ちるのが理解できませんでした。

デバッグ中にすぐに熱くなるスマホが不快に感じられ、初めてプロファイラを使った最適化に挑戦しました。プロセスは思ったより単純で、Unityプロファイラが録画したデータ区間の中でフレームが高く測定される部分について、どの作業が最も多く実行されているかを探し、該当部分を改善するだけでした。

私の場合、Semaphore.WaitForSignalが50〜70%ほどのシェアを占めていましたが、この場合主にシェーダーを軽いものに変更する作業を推奨するという記事を見て、以前に探したシェーダーファイルをより軽いものに交換したところ、フレームがかなり上昇し、発熱が相当減る経験ができました。

リリース基準

完走のための目標の必要性

様々なオブジェクトについてそれぞれのアニメーションとインタラクションを作ることは基本的に楽しく興味深いことですが、時間と労力が思ったより多くかかると感じました。徐々に熟練しノウハウが増えるにつれて作業効率が上がると思っていましたし、実際にかなり上がりましたが、コードを入力したりキーフレームアニメーションを作ったりする作業はタイプを打ったり画面に線を引いたりする最低限の物理的労働を要求していました。

プロジェクトが大きくなり、対応すべきアセットが増えるにつれ、徐々に自分が背負っている負担が増えていることを実感し始めました。以前Unityが発行したゲーム業界レポートで、“Don’t bite off more than you can chew”というアドバイスを見たことがありますが、今の自分の状況がそういう方向に向かっているのではないかと悩みました。

そこで目標地点としてのリリース基準が必要だと考え、当分はGoogle Featuringを申請できる程度を目標にすることにしました。Google Featuringは高品質のアプリとゲームに関する基準を明確に提示しており、その中には代表的に以下のようなものがあります。

特にAndroid Developersでは、良いユーザー体験についてユーザビリティ(バックアップと復元など)、アクセシビリティ、ローカライズ、ディープリンク、視覚的魅力と職人精神(アニメーション、オーディオ、コントロールなど)… これ以外にも多くの基準と事例を提示しています。もう少し詳細化する必要がありますが、大きな基準としては参考にできそうです。

その他自己提示する詳細基準

  • アプリ
    • アプリアイコン
    • 3Dサウンド
    • 簡単なチュートリアル
    • 内部テキストのローカライズ
  • オブジェクト
    • 5種類以上のオブジェクト
    • オブジェクト別2種類以上の個性
    • オブジェクト別3種類以上のインタラクション
  • 背景
    • 雨、雪などの天気システム
    • 雲を含む動的スカイボックス
    • 画面に3つ以上の背景オブジェクトを保証

おわりに

gantt
    title 1次ロードマップ

    Section 企画
    企画 :a1, 2024-02-28, 1d

    Section 開発
    プロトタイプ開発 :a2, 2024-02-28, 85d
    ビジュアル構成: a3, 2024-05-23, 10d

    Section リリース
    リリースおよびサポート :a4, 2024-06-01, 213d

    %% a2["プロトタイプ完成"] : 初期バージョンのプロトタイプを開発して機能を確認しテストします。

元のロードマップでは記事が発行される時点の今日または明日の完成を目標としていましたが、能力不足かかなり及ばなかったです。ロードマップも新たに提示し、何よりももう少し四半期ごとの役割と目標をより詳細に決める必要がありそうです。

追加で、6月に補充役の兵役履行が始まるため、当分は開発を置いて訓練所に行かなければなりません。今後の状況がまだよくわからないので可能かはわかりませんが、それでもストア登録が可能なレベルを目標に開発を着実に続けていきたいです。