tanaka's Programming Memo

プログラミングについてのメモ。

PostProcessing Stack v2を使う

f:id:am1tanaka:20180518095534p:plain

ようやくUnity2018.1に手をつけたところ、PostProcessing Stack v2でつまづいたのでメモです。

目次

PostProcessing Stack v2の初期設定

Asset Storeにある古いやつと比べると少し手順が増えているので、公式ドキュメントに沿った手順です。

PostProcessing Stack v2をプロジェクトに追加

既存のPostProcessing Stackを使っていないプロジェクトや、3Dのテンプレートで新規にプロジェクトを作成した場合、初期設定が必要です。以下の3D With Extras以下のテンプレートでは初期設定済みなのでこの手順は不要です。Post Processの調整にすぐに進めます。

f:id:am1tanaka:20180518084032p:plain

PostProcessing Stack v2をPackage Managerからプロジェクトに読み込み、カメラとボリュームオブジェクトを設定していきます。

  • Unity2018.1.xを起動したら、WindowメニューからPackage Managerを選びます

f:id:am1tanaka:20180518083357p:plain

  • All -> PostProcessing -> Install 2.0.5-previewの順にクリックしていきます

f:id:am1tanaka:20180518084513p:plain

  • インストールが完了したら、Packagesダイアログの右上のxをクリックして閉じます

Cameraにレイヤーを設定

PostProcessingを適用したいカメラにPost-process Layerコンポーネントを追加します。

  • HierarchyビューからPostProcessingを適用したいカメラを選択します
  • InspectorビューでAdd Componentをクリックして、Rendering -> Post-process Layerをクリックして追加します

f:id:am1tanaka:20180518084955p:plain

f:id:am1tanaka:20180518085123p:plain

  • Anti-aliasingは任意で。モバイルやVRなど軽量にしたい場合はFXAA、デスクトップなど高負荷で構わない場合は用途に合わせてSMAA, TAAでもよいでしょう

Trigger

Triggerは、後に設定するPost-process Volumeのうち、Localなものを発動させる距離を決めるtransformのオブジェクトを指定します。通常はデフォルトでアタッチしてあるカメラのままで構いません。トップビューのゲームの場合、カメラではなく、プレイヤーオブジェクトからの距離で発動範囲を設定できた方が便利かも知れません。そのような時、ここにプレイヤーオブジェクトを設定します。

Layer

このカメラが影響を受けるPost-processing Volumeを設定したゲームオブジェクトのレイヤーを設定します。Unity2018.1.xにはデフォルトでPostProcessingレイヤーが定義されているので、設定するとよいでしょう。古いプロジェクトに適用する場合など、レイヤーがない場合は自分で追加してください。無効なオブジェクトを含めるとパフォーマンスに影響するので、DefaultやEverythingを選択するのは推奨されていません。

Anti-aliasing

Post Processによるアンチエイリアシング(ドットのギザギザを滑らかにする処理)を使いたい時に設定します。FXAAがモバイル用の軽量なもの。SMAAはハイクオリティーですが、モバイルには不向きで、VR/ARでは現状で非対応のもの。TAAは過去のフレームなどを使ったアルゴリズムでやはりFXAAより高負荷で、リソースも食い、数年前のopenGLES2のモバイル端末は非対応のものです。FXAAを選択しておいて、必要に応じてその他のものに変更して様子を見るのが良さそうです。

Stop NaN Propagation

真っ黒な場所にPost Processを適用しようとすると無効な計算が行われておかしな現象が起きたりするので、それを防ぐ設定です。基本的にtrueのままにしておくのがよいでしょう。

Post-process Volumeを設定

これがv2で新しく増えた設定です。Post Processを適用する範囲や内容を個別に設定して、レイヤーやTriggerからの距離で適用範囲を切り替えられるようになりました。シーン全体で設定する場合は、1つだけ設定すれば構いません。それ用の空のオブジェクトを作成することが推奨されていますので、それに従います。

  • GameObjectメニューからCreate Emptyを選択して、空のゲームオブジェクトを作成します。ゲームオブジェクトの名前はPostProcess Volumeなどにしておくとよいでしょう
  • InspectorビューのLayerで、先ほどカメラのLayerに設定したものを設定します。今回はPostProcessingです

f:id:am1tanaka:20180518091848p:plain

  • InspectorビューからAdd Componentをクリックして、Rendering -> Post-process Volumeを選択して追加します

f:id:am1tanaka:20180518091932p:plain

  • シーン全体に適用して構わない場合は、Is Globalをチェックします

f:id:am1tanaka:20180518092705p:plain

ここにチェックを入れないと、このゲームオブジェクトと、カメラのPost-process LayerTriggerに設定したオブジェクトの距離がBlend Distance欄で設定した距離以内になった時に、Post Processが発動するように設定できます。

  • Profile欄のNewボタンをクリックして、このPost-process Volumeで発動させたいプロファイルデータ用のアセットを生成します

f:id:am1tanaka:20180518092718p:plain

以上で、Post Processの初期設定完了です。効果を設定していきます。

Post Processを設定する

Post Processの内容は、Post-process Volumeオブジェクトで設定できます。定番のBloomを設定してみます。

  • Hierarchyビューで、設定したいPost-process Volumeが設定されているオブジェクトを選択します

f:id:am1tanaka:20180518092955p:plain

  • InspectorビューのPost Process VolumeコンポーネントAdd effect...ボタンをクリックします

f:id:am1tanaka:20180518093043p:plain

  • Unity -> Bloomを選択します

f:id:am1tanaka:20180518093337p:plain

  • InspectorビューにBloomが追加されるので、クリックして開きます

f:id:am1tanaka:20180518093500p:plain

Bloomが使えない ?

ここでものすごく引っかかりました。全ての項目が無効になっていて操作できません...。何が悪いのかと色々と調べまくった後、左の丸の部分がクリックできることに気づきました...。

f:id:am1tanaka:20180518093631p:plain

  • Intensityの左の●をクリックして有効にしたら1を入力します

f:id:am1tanaka:20180518094016p:plain

以上でBloomが有効になります。他の項目もチェックを入れれば使えるので必要に応じてチェックを入れて設定してください。あとは光らせたいオブジェクトのマテリアルの設定をします。

オブジェクトを輝かせる

Sphereなどを作成したら、Materialを作成して適用します。

  • Bloomの効果を出すには、自己発光させますので、マテリアルのEmissionにチェックを入れます

f:id:am1tanaka:20180518094249p:plain

  • EmissionのColor欄をクリックします

f:id:am1tanaka:20180518094331p:plain

  • 輝かせたい色を設定したら、Intensity欄を1以上の値にします。例では5にしています

f:id:am1tanaka:20180518094353p:plain

光りました!

f:id:am1tanaka:20180518094451p:plain

Directional Lightを日没させて、SphereのIntensityを3程度に下げて、全てのオブジェクトをStaticにしてみました。やっぱBloomいいですね!

f:id:am1tanaka:20180518095534p:plain

まとめ

v2では、カメラへの設定に加えて、発動条件を設定できるPost-processing Volumeの設定が必要になりました。これにより、シチュエーションや環境に応じて、自動的に演出を切り替えられるようになりました。また、それぞれのエフェクトの項目ごとに有効/無効を設定できるようになったので、パフォーマンスも良さそうです。

注意点としては、多くの機能がデフォルトでは無効になっていることです。何らかの設定をしないと効果が現れず、あれ?となることが増えたように思います。このような設定は初心者には厳しいので、正規版では修正して欲しいところです。また、公式機能にも関わらず、UIのデザイン方針が他の機能と異なるのはよくありません。この辺り、今後の改良に期待です。

参考URL

AtomでCannot load the system dictionary for 'ja_JP'というエラーが発生した

macAtomでファイルを開いた時にCannot load the system dictionary for 'ja_JP'というエラーが表示されていたのを対処した方法です。

f:id:am1tanaka:20180519145702p:plain

原因はこちらの模様。

spell-check throws an error at atom launch · Issue #253 · atom/spell-check · GitHub

Atomにデフォルトでインストールされているスペルチェックのパッケージが、英語以外のシステムだと設定ファイルが見つけられずに、それを知らせるためにエラーを出しているようです。

スペルチェックいらない、という場合はパッケージを無効にすればエラーは出なくなります。

  • AtomメニューからPreferencesを開きます
  • Packagesを選択して、検索欄にspellと入力します
  • spell-checkが列挙されたら、Disableボタンをクリックします

以上です。

Atomの日本語スペルについては、atom spell-check 日本語で検索すると色々と出てくるので、スペルチェックを利用するにはそれらを調べて見ると解決するかも。

Mesh Bakerを使ってみた(LODについて追記)

シーン内の別々のゲームオブジェクトで構成されるメッシュを、マテリアルやシェーダーごとに合体、あるいは、マテリアルも合体させて、ドローコールを減らして高速化してくれるという人気アセットMesh Bakerを使ってみました。

紹介に先立って補足

Mesh Bakerを利用して効果があるのは、多くのマテリアルやシェーダーをバラバラに使っているオブジェクトで構成したシーンです。同じマテリアルを使ったシーンの場合は、Mesh Bakerを利用するメリットは少ない可能性があります。

また、Mesh Baker LODは、事前に用意したポリゴン数を減らしたモデルをこちらで用意して、それを切り替えてくれるというものです。自動的にポリゴン数の削減をやってくれる訳ではないのでご注意ください。これは、Unity謹製のLOD Groupも同様です。

条件に合致した上で、自前でポリゴン数を減らしたモデルを用意すれば、かなりの効果が期待できます。

(2018/5/17追記)

目次

利用したシーン

体験講義用に作成したUNetのマルチ対戦的プロジェクトに適用してみました。立方体や、ProBuilderの円柱、階段などを使ってステージを作ったので形はシンプルなのですが、思いのほか色々と置いてしまったのでそれなりに重そうなステージになっていました。

Mesh Baker適用前はこんな感じでした。

f:id:am1tanaka:20180510223601p:plain

f:id:am1tanaka:20180510223608p:plain

黄緑の足場をMesh Bakerで合体させます。ただし、1つに統合するとカリングなどで不利になるので、適当なグリッドで分割します。

Mesh Bakerでメッシュを統合する

Asset Storeで購入して、通常通りダウンロード&インポートしました。セール中に購入したので$45.5で買えました^^

チュートリアルを見る

動画チュートリアルが用意されていたので、以下の2つを見ました。

www.youtube.com

www.youtube.com

ゲームオブジェクトを準備する

Mesh Bakerを使ってメッシュを統合するには、TextureBakerオブジェクトをシーンに配置します。対象のプロジェクトを開いて、Asset StoreからMesh Bakerをダウンロード&インポートしてから作業してください。

  • GameObjectメニューから、Create Other -> Mesh Baker -> TextureBakerを選択します

f:id:am1tanaka:20180511004249p:plain

以上で、HierarchyビューにTextureBaker(0)というオブジェクトが生成されます。これを使って、メッシュの選択やマテリアルの結合、Mesh Bakerオブジェクトの作成などを行います。

オブジェクトを選択する

くっつける対象のゲームオブジェクトを選択します。最初のチュートリアルでは、メッシュを持ったゲームオブジェクトを一つずつドラッグ&ドロップしていますが、このシーンのメッシュは階層構造になっている上に200を越えるオブジェクトがあるのでやってられません。そこで、Adding Objectsツールを利用します。

  • HierarchyビューのTextureBaker(0)をクリックして選択します

f:id:am1tanaka:20180510224730p:plain

  • InspectorビューからOpen Tools For Adding Objectボタンをクリックします

f:id:am1tanaka:20180510225038p:plain

  • ダイアログが開くので、Search For Meshes To Addボタンをクリックします

f:id:am1tanaka:20180510225124p:plain

  • Hierarchyビューで、統合したいゲームオブジェクトを選択しておきます

f:id:am1tanaka:20180510225625p:plain

  • MB3_MeshBakerダイアログで、追加するオブジェクトの条件を設定します。今回は以下のようにしました。
    • Staticなオブジェクトにする
    • Enableなオブジェクトにする
    • UVが範囲外のオブジェクトもあるので、それは除外しません
    • すでに追加済みのオブジェクトは除外します

f:id:am1tanaka:20180510225455p:plain

  • 以上設定したら、Add Selected Meshes To Targetボタンをクリックします

以上で選択完了です。Inspectorビューで、Object To Be Combinedの左の三角アイコンをクリックして開いてみてください。条件にあったオブジェクトが選択されているはずです。

f:id:am1tanaka:20180510225940p:plain

結合マテリアルとBakerオブジェクトの生成

次に、結合したマテリアルやシェーダーと、Bakeを行うためのオブジェクトを生成します。

  • Analyse Scene & Generate Bakersボタンをクリックします

f:id:am1tanaka:20180510230150p:plain

  • グループ分けする基準があれば設定します。今回はデフォルトのままにしました
  • 結合マテリアルを保存する先のフォルダーを指定するために、Select Folder For Combined Material Assetsボタンをクリックします

f:id:am1tanaka:20180510230437p:plain

  • Assetsフォルダーから、必要なら新しくフォルダーを作成して、フォルダーを選択します

f:id:am1tanaka:20180510230426p:plain

  • List Shaders In Sceneボタンをクリックします

f:id:am1tanaka:20180510230437p:plain

指定したグループ分けの基準に沿って、シーン内のシェーダーとマテリアルがグループ化されます。

f:id:am1tanaka:20180510230642p:plain

  • リストアップされたGenerate Bakerボタンをクリックしていって、統合マテリアルとBakerオブジェクトを生成します

f:id:am1tanaka:20180510230918p:plain

f:id:am1tanaka:20180510231020p:plain

HierarchyビューにはBakerオブジェクトが、Projectビューの保存先として指定したフォルダーにはマテリアルとシェーダーが生成されます。

f:id:am1tanaka:20180510231245p:plain

f:id:am1tanaka:20180510231108p:plain

統合メッシュを生成する準備が整いました。

Adding Objectツールは役目を終えたので閉じて構いません。

クラスター分割する

このまま生成すると、シーン全体がまとめられてしまいます。ドローコールは減るかも知れませんが、カリングが効かなくなるので描画ポリゴン数が増えてしまう恐れがあります。適切なサイズに分割して生成するようにします。

  • HierarchyビューのMeshBaker-Standard-LM-1の左の三角をクリックして開きます

f:id:am1tanaka:20180511010004p:plain

  • 子供のMeshBakerは、まとめてオブジェクトを生成するためのものなので、分割する場合は不要です。選択して削除します

  • HierarchyビューのMeshBaker-Standard-LM-1をクリックして選択し直します

  • InspectorビューからCluster Type欄を見つけて、Agglomerativeに変更します

f:id:am1tanaka:20180511012142p:plain

  • 今回のシーンは大きいので、Max Distanceを最大の10にしておきます

f:id:am1tanaka:20180511012154p:plain

  • InspectorビューのBake Materials Into Combined Materialボタンをクリックして、マテリアルを再生成しておきます

f:id:am1tanaka:20180510234541p:plain

  • Click To Build Clustersボタンをクリックします

f:id:am1tanaka:20180511012239p:plain

エラーが発生しましたが、とりあえず動いたので気にせず進めました。

  • Generate Mesh Bakersボタンをクリックして、Bakerを生成します

f:id:am1tanaka:20180511011016p:plain

これで、MeshBakerが自動的に判断したエリアに分割してくれました。

統合したメッシュオブジェクトを生成する

統合したメッシュオブジェクトを生成します。

  • InspectorビューのBake All Child MeshBakersボタンをクリックします

f:id:am1tanaka:20180510234910p:plain

Hierarchyビューに、分割されたメッシュオブジェクトが生成されました。

f:id:am1tanaka:20180511012717p:plain

他にもオブジェクトがあれば、同様の手順で生成していきます。

仕上げ

元のオブジェクトを削除したり、当たり判定を入れたりして仕上げます。

元のオブジェクトを消す

元のオブジェクトをDisableにするだけであれば、HierarchyビューからTextureBaker(0)を選択して、InspectorビューでDisable Renderers On All Child MeshBaker Source Objsボタンをクリックすれば、自動的に該当するオブジェクトを無効にしてくれます。

f:id:am1tanaka:20180510231739p:plain

完全に不要な場合は、Hierarchyビューから削除してもよいでしょう。

f:id:am1tanaka:20180510231851p:plain

関連オブジェクトの削除

役目が終わったら、TextureBaker(0)なども消して構いません。

f:id:am1tanaka:20180510232002p:plain

当たり判定の設定

元のオブジェクトを削除してしまったので、当たり判定も消えてしまいました。Mesh Colliderを追加して、当たり判定を復活させます。

  • Hierarchyビューの検索ボックスに-mesh-と入力すると、統合したメッシュオブジェクトが表示されるので、すべて選択します

f:id:am1tanaka:20180511013201p:plain

  • InspectorビューでAdd Componentをクリックして、Physics -> Mesh Colliderを追加します

f:id:am1tanaka:20180510232330p:plain

Staticオブジェクトにしたいので、その設定をします。

  • Hierarchyビューの検索ボックスにCombinedMesh-と入力すると、統合メッシュオブジェクトの親が表示されるので、すべて選択します

f:id:am1tanaka:20180511013327p:plain

  • InspectorビューのStaticにチェックを入れます

f:id:am1tanaka:20180510232741p:plain

  • 子供もすべてstaticにしたいので、Yesをクリックします

f:id:am1tanaka:20180510232757p:plain

以上で完了です。Hierarchyがそのままだと使いづらいので、検索ボックスのxをクリックして検索を解除しておきましょう。

f:id:am1tanaka:20180511013457p:plain

成果

以上で完了です。成果を確認してみます。

f:id:am1tanaka:20180510235656p:plain

もともとマテリアル一つだったので、ドローコールは変化ない模様。Saved by batchingは667から0になってます。

効果的ではなかろうかというのはShadow castersの数で、607から33に激減。

しかし、ポリゴン数が増えちゃいました。

f:id:am1tanaka:20180510235731p:plain

上空ビューも似たような傾向で、Shadow castersが激減してます。

ポリゴン数が増えたことによってパフォーマンスは相殺されて、ほとんど差が分からなかった、というのが今回の結果でした^^;

まとめ

オブジェクトを統合することで、Shadow castersを大幅に減らすことに成功しました。しかし、オブジェクトを統合したことで描画対象のポリゴン数がうまく減らず、パフォーマンスの向上は微妙でした。

本来は、沢山マテリアルやシェーダーがあるシーンで、それらを統合してドローコールを減らすのが目的の機能なので、マテリアルをそれほど使ってないシーンだと効果はあったりなかったりでした。

しかし弾は残っています。Mesh Bakerの追加アセットMesh Baker LODも入手しています。これはLOD(Level Of Detail=距離に応じてモデルのポリゴン数を切り替える機能)をやってくれるやつで、まさにポリゴン数を減らしてくれるやつです。これと組み合わせた時に真価を発揮するに違いないと期待しています。

参考URL

Unity Analyticsを利用する

ずっとやろうやろうと思っていて放置していたUnity Analytics(アナリティクス)をようやく組み込んでみました。簡単に手順をまとめました。

目次

対象環境

  • Unity2018.1.0f2 / 2017.4.x / 2017.3.xで確認

Unity Analyticsとは

公式マニュアルで気になった部分のみ抜粋です。

Unity Analyticsを設定するだけで、月間アクティブユーザー(MAU)、日別アクティブユーザー(DAU)、そして新規ユーザー数を確認することができます。Unity AdsやIAPサービスを利用していれば、それらの統計データも確認できます。 プレイヤーがゲーム内でどのような行動をしたかを知るために、プレイヤーが動作を行った際にStandard Analytics Eventを発生させることで、Analyticsのデータに含めることができます。これにより、チュートリアルを確認したか、IAPストアを訪れたか、想定したようにプレイヤーが上達しているかなどを知る手掛かりが得られます。 また、アプリのアップデートをせずに、Remoteセッティングを使うことでプレイヤーに適したゲーム拡張を配信することができます。

ざっくりと、アプリをリリースした後に、どのようなユーザーに利用されているのか、用意したチュートリアルなどが読まれたか、ゲームをどこまで進めたのかなどの情報を収集することができるUnity Cloudのサービスの一つということです。

コアデータ

Unity Servicesの設定でAnalyticsを有効にするだけで、以下のデータを自動的に収集することができます。

  • 新しくインストールされた数
  • 日間アクティブユーザー数
  • 月間アクティブユーザー数
  • 合計セッション
  • ユーザーあたりのセッション数
  • アプリで遊んでいた時間
  • 国やプラットフォーム

Player behaviour data(プレイヤーの行動データ)

プレイヤーの行動を把握するには、AnalyticsEventを利用します。どのシーンを開いたかや、ステージをクリアしたり重要アイテムを取得したユーザーがどれぐらいいるかを調査して、ゲームがどのぐらい遊ばれたか、どの辺でユーザーが脱落しているかを把握することができます。

また、ゲームを開始した時に起動してから何回目のゲーム開始かや、ゲームオーバー時のレベル、ゲームオーバーの原因、スコアなどをカスタムイベントで送信することで、より詳細な情報を得ることができます。

その他

他にもあれこれ機能がありますが、今回の目的はPlayer behaviour dataで解決できるので省きますが、Remote Settingsは気になっています。Analyticsダッシュボードからゲーム内の設定値を変更することができる機能で、アプリを公開した後でこの値を変更すれば、プログラムの更新なしでバランス調整ができるようです。 作成した様々なRemote Settingsをエディター内でゲームオブジェクトに割り当てることができるそうです。

以下のように活用できそうです。いずれ調べよう。

  • ゲームバランスの調整
  • 機能の有効/無効設定
  • 画面のテーマを変更する

Analyticsを有効にする

新規プロジェクトで有効にする

新規プロジェクトでAnalyticsを有効にするには、ログインした上で、プロジェクト作成時にEnable Unity Analytics欄をONにして、プロジェクトを作成します。

f:id:am1tanaka:20180503133350p:plain

既存のプロジェクトで有効にする

開発済みのプロジェクトに組み込む手順です。

  • クラウドボタンをクリックして、Servicesタブを表示します
  • 以下のような画面が表示されたら、ユーザーを選択して、Createボタンをクリックして、UnityCloudにプロジェクトを作成します

f:id:am1tanaka:20180503133729p:plain

  • Unity Cloudにプロジェクトを作成していたら、以下のメニューが表示されるので、AnalyticsのスイッチをクリックしてONにします

f:id:am1tanaka:20180503133850p:plain

  • ANALYTICSのDiscover player insightsを有効にして、Enable Analyticsボタンをクリックします

f:id:am1tanaka:20180428174102p:plain

  • Designation for Apps Directed to Children Under the Age of 13欄は、13歳未満の子供が使っても大丈夫なアプリならチェックを入れて、Continueをクリックします
  • COPPA compiance changedと表示されたらAnalyticsの有効化成功です。COPPA...の表示はxをクリックして閉じて構いません

f:id:am1tanaka:20180428174707p:plain

動作確認

  • UnityをPlayします。数秒すると、Servicesタブに以下のようにAnalyticsデータが表示されます

f:id:am1tanaka:20180503134135p:plain

deviceInfoで起動したデバイスの情報、appInstallとappStartにはインストールされたプラットフォームとUnityのバージョンが表示されています。このデータは、1日後ぐらいにUnity Cloud上で集計されて、ダッシュボードでも確認できるようになります。これだけでも、例えばiPhone向けに配信したアプリがどのiPhoneにどのぐらいインストールされたかや、利用されているAndroid端末の傾向などを把握することができるので有益だと思います。

プレイヤーがどこまでゲームを進めたのかを把握する

Unity Analyticsの機能の一つに、Level Progression(レベルの進み方)があります。どのぐらいのユーザーが、どのレベル(チュートリアルの画面やゲームのステージ)まで進めたかを把握するためのものです。これを利用すれば、ユーザーがチュートリアルを利用しているかや、チュートリアルのどこかで脱落していないか。あるいはユーザーが一気に脱落するステージはないか。また、ステージが進んでいるということは、その端末でゲームが動作している確認もできます。

これをやるためには、ゲームが進んだことをAnalyticsイベントで送信します。staticメソッドを呼び出すだけですのでとても簡単です。

レベルの開始と完了を送信する

ステージ開始時と完了時にステージ数を送信して、プレイヤーがどこまでゲームを進めたかを把握できるようにしてみます。AnalyticsEventというクラスがProgression(進み方)を送信するための以下のようなstaticメソッドを提供しています。

イベント名 概要
game_start 新規にゲームを開始
game_over ゲームオーバーになった
level_start レベルを始めた
level_complete レベルをクリアした
level_fail レベルをクリアできなかった
level_quit レベルをクリアせずに抜けた
level_skip 過去のレベルをスキップした
level_up ランクが上がったり、RPGなどでレベルアップした

知りたいパラメーターを渡して、上記のいずれかのイベントを呼び出せばUnity Cloudに情報が送信されて記録されます。

※これらのメソッドは、送信されるイベントの名前が上記のようになるというだけで、どれを使わなくてはならない!というものではありません。それらしいやつを選んでください。

実装

Level Progressionには、level_startlevel_completeを利用するのがセオリーのようです。ステージ開始時にlevel_startを、クリア時にlevel_completeを送信するように実装します。現在のステージ数が変数nowLevelに格納されているものとします。

  • イベントを送信するコードの先頭で、以下を定義します
using UnityEngine.Analytics;
// 2017.3より前のバージョンの場合は、using UnityEngine.Analytics.Experimental;
  • ステージ開始時に、以下を呼び出します。
        AnalyticsEvent.LevelStart(nowLevel);
  • ステージクリア時に、以下を呼び出します。
        AnalyticsEvent.LevelComplete(nowLevel);

LevelStart()メソッドとLevelComplete()メソッドは、どちらも引数としてint型かstring型を最低1つ受け取り、開始するステージ数やステージ名を渡します。また、Dictionary<string, object>()で追加のパラメーターを作成して、2番目以降の引数で渡すことで、独自のパラメーターを送信することもできます。

上記を実装したらUnityでPlayして、レベルの開始とクリアを実行してください。デバッグキーを仕込んだり、ボタンで試すと楽です。

実行してから数秒待つと、Servicesタブにlevel_startlevel_completeの情報が追加されます。

f:id:am1tanaka:20180503150243p:plain

これでプログラムは完了です。とても簡単です。次に、このデータを分析するためのFunnelを作ります。

プレイヤーの進み方を確認するFunnelの作成

Unity Analyticsはデータの送信は簡単なのですが、分析方法にクセがあります。Servicesタブに表示されるようなデータが得られればExcelなどで分析すればよいのですが、生データを得るにはProライセンスが必要です。Proライセンスを持っていない場合は、用意されている分析ツールを利用します。

プレイヤーが何をしたかを確認するにはFunnel Analyzerを利用します。

Funnelを作成する

Unity Cloudのダッシュボードを開きます

  • Servicesタブの右上のGo to Dashboardをクリックします

f:id:am1tanaka:20180503144051p:plain

f:id:am1tanaka:20180510155850p:plain

  • 画面左からAnalyticsの下のFunnel Analyzerをクリックします

f:id:am1tanaka:20180503144227p:plain

  • 進み具合を知るには、Level Progressionのテンプレートを利用するが楽なのでクリックします

f:id:am1tanaka:20180503150457p:plain

  • 確認したいイベントであるlevel_startlevel_completeが設定済みになっています

f:id:am1tanaka:20180503150737p:plain

  • 確認したいレベル数を設定します。特にルールはないので、自分が把握しておきたいというレベル数を入力しておきます。例えば20ステージまで把握したいなら、Num Levelsを20にして次へをクリックします

f:id:am1tanaka:20180503151116p:plain

  • 以下のように、テンプレートに従ってファネルが設定されます

f:id:am1tanaka:20180503151249p:plain

  • 一番下まで見ると、level_startlevel_index20のものと、level_completeの同様の設定を確認できます。1~20ステージの開始と完了が設定できているということです

f:id:am1tanaka:20180503151338p:plain

  • 問題がなければ保存をクリックして確定します

f:id:am1tanaka:20180503151531p:plain

以下のメッセージが表示されれば完了です。このダイアログのxをクリックして閉じて構いません。

f:id:am1tanaka:20180503151611p:plain

あるレベル以上までクリアできているかを確認したい場合のファネル

Level Progressionは、あるシナリオに沿ってプレイヤーが進めているかを確認するのが目的の機能のようです。そのため、設定と異なる順番で送られてきたレベルについては無視されてしまいます。

また、Unity Analyticsは送信されてくるイベントの記録がかなり遅いようで、頻繁にレベルアップするようなゲームの場合、実際に送信した順番と、Unity Analyticsが受け取る順番が前後してしまうことがあるようなのです。

あるレベルまで到達したかを確実に把握するには、先の設定は適さない可能性があります。そこで、特定の基準となるレベルまで到達したかを別のファネルを作成して確認するようにしました。

  • ファネル分析画面の右上の作成するファネルの右の▼をクリックします

f:id:am1tanaka:20180510162454p:plain

f:id:am1tanaka:20180510162537p:plain

  • Funnel Nameや説明を適宜設定して、レベル数は1次へをクリックします

f:id:am1tanaka:20180510163025p:plain

  • level_start1以上、level_complete5以上を設定して、保存します。

f:id:am1tanaka:20180510163547p:plain

送られてくるレベル数が多少前後しても、確実に目的のレベルを超えたかを確認しようという狙いの設定です。

分析の前に

では、いざ分析!と行きたいところですが、Unity Analyticsではファネルを作成したり、イベントデータを送信してからダッシュボードに反映されるまでに、1日程度かかります。

プロジェクトをビルドして、色々なデバイスWebGLからイベントを送信したら、一日寝かせてください。Unity AnalyticsはスマホWebGLなど、多様なプラットフォーム上で動きますので、この機会にあれこれビルドして実行するのもよいでしょう。

結果を確認する

一日経過したらデータを確認してみましょう。

Funnelを確認する

Funnelを作成した時と同じ要領で、AnalyticsタブのGo to Dashboardをクリックしてダッシュボードを開き、GO TO ANALYTICSをクリックして、AnalyticsFunnel Analyzerを開きます。

f:id:am1tanaka:20180510160439p:plain

分析が終了していると、以下のようなグラフが表示されます。これを見ると、一人遊んでいて、レベル2まで完了した、ということが分かります。

f:id:am1tanaka:20180510160645p:plain

しかし、実際にはもっと上のレベルまでクリアデータは送信してありました。これは失敗例です^^;

Event Managerを確認する

本当に送られてきたデータが信用できるかは、Event Managerで送信されてきたイベントデータを見ることで確認できます。

  • 画面左のメニューからEvent Managerをクリックします

f:id:am1tanaka:20180510161330p:plain

  • 下にスクロースしてカスタムイベント欄を表示させたら、確認したいイベントをクリックして開きます。例えば、level_completeをクリックして、さらにlevel_index Aをクリックします

f:id:am1tanaka:20180510161516p:plain

確認すると15レベルまでクリアデータがあるので、先のファネルでは目的の情報が記録できていなかったということが分かりました。

では、もう一方のレベル5までクリアできているかを確認するファネルに切り替えましょう。

f:id:am1tanaka:20180511221642p:plain

こちらでは、level_complete > 5に値が入っているので、ちゃんとレベル5がクリアできているかが確認できました。この辺りの運用には注意が必要そうです。

Analyticsを利用する上での注意点

Analyticsを利用する上で気付いた注意点です。

  • Unity AnalyticsでのStandardイベントやカスタムイベントの送信回数は、ユーザーごとに1時間あたり100回までに制限されています。1時間以内に100回以上のイベントを送信すると、101回目以降のデータは破棄されます
  • 2017.3以前のUnityでStandardイベントを利用する場合は、事前にアセットストアからStandard Events SDKをダウンロードしてインポートする必要があります
    • 自分はUnity2017.3やUnity2018.1を利用したので、アセットのインポートは不要でした。
  • Level Progressionは、想定した順番でレベルがクリアされたかどうかを判定する機能のようです。Analyticsに反映される前に次のレベルクリアの情報が送られてしまうと、実際にはクリアしているのにそのように集計されないので注意が必要です

調べきれていないので、もっとよい方法があるかも知れませんが、現状ではこんな感じでした。

まとめ

なんとなく敬遠していたAnalytics機能でしたが、使ってみるとめちゃくちゃ簡単に使えました。一方で、データの活用方法はちょっとクセがあって注意が必要そうでした。

今回は到達レベルのみでしたが、カスタムパラメーターを利用すれば、ゲームオーバー時の状況を送信したり、エラー報告を送信したり、フレームレートを送信して想定した速度で動作しているかを把握するなど様々な活用ができます。

ちゃんと運用するなら、生データがダウンロードできて、プレイヤーの移動軌跡を表すヒートマップも使えるProライセンスは強いなと思いました。

最後に。配布するアプリで利用する場合は、どのようなデータを送信するかを明示してユーザーの同意を得ておいた方がよいだろうと思います。

参考URL

Phaser3の最新版のTern設定ファイルを作成する

AtomでPhaserのコード補完をする設定をこちらに書きました。Phaser3はまだリリースされたばかりで、ドキュメントが全部揃っていなかったり、機能が抜けていたり、仕様が変化しています。

ドキュメントもすぐに新しいものが出てくる状況なので、更新をセルフサービスでできるように手順をまとめておきます。

目次

  • 目次
  • 前提
  • 必要なリポジトリーをクローンする
    • はじめの一回
    • 上記の作業をすでにやっていたら
  • 最新のJSONファイルを作成
  • Tern用のデータを作成する
  • まとめ
  • 関連URL
  • 備忘録
    • エラーの調査方法
    • 作業時のコツ
    • 誤記の修正(Phaser-CE)

前提

必要なリポジトリーをクローンする

ドキュメントの作成に必要な以下の2つのリポジトリーの最新版を入手します。

はじめの一回

はじめて作業する時は、リポジトリーのクローンをします。すでに一度クローンしていたらこちらに進んでください。

  • LXTerminalなどのターミナルを起動します
  • 作業フォルダーに移動します。例えば、ユーザーフォルダーのphaser3-projectsというフォルダーなら以下の通り
cd ~/phaser3-projects
  • 以下で、phaser3phaser3-docsリポジトリーをクローンします
git clone git@github.com:photonstorm/phaser.git
git clone git@github.com:photonstorm/phaser3-docs.git

以上で完了です。JSONのファイルを作成に進んでください。

上記の作業をすでにやっていたら

新しくリリースされたバージョンに対応させたい場合は、以下の手順になります。

  • はじめの時と同様、LXterminalなどを開いて、作業用フォルダーへ移動します
  • 以下を実行します
cd phaser
git pull origin master
cd ..
cd phaser3-docs
git pull origin master

以上で、phaserとphaser3-docsが最新の状態になります。

これらのプロジェクトはこちらでは変更しないので、ここでは問答無用でプルをしてます。もし開発しているプロジェクトだった場合は、手順を踏んで更新してください。

最新のJSONファイルを作成

最新版のPhaser3のJSDocから、Ternの設定ファイルの元となるJSONファイルを作成します。

  • LXTerminalなどのターミナルで、phaser3-docsフォルダーに移動します
  • 以下を実行します
npm run json
  • ファイルのパース(解析)が始まるので、終わるまで待ってください。以下のような画面になれば完了です。

f:id:am1tanaka:20180410170520p:plain

仮想PCのLubuntuで20秒ちょっとでした。PCの性能次第ですが、1分程度待つつもりでいれば完了するでしょう。

Tern用のデータを作成する

作成されたファイルは、json/phaser.jsonとして保存されます。これを、Phaserのプロジェクトのnode_modules/tern-phaser/generator/data/jsdoc-ast.jsonにコピーします。

  • phaser3-docsフォルダーで以下のコマンドで、jsonフォルダーをファイルマネージャーで開くことができます
pcmanfm json
  • phaser.jsonファイルを右クリック -> コピーなどでコピーします

f:id:am1tanaka:20180410171425p:plain

f:id:am1tanaka:20180410171611p:plain

  • node_modules -> tern-phaser -> generator -> dataフォルダーをダブルクリックで開いていきます
  • [Ctrl]+[V]キーなどで、先ほどコピーしておいたphaser.jsonをデータフォルダー内に貼り付けます

f:id:am1tanaka:20180410171816p:plain

  • jsdoc-ast.jsonを選択して、[Delete]キーなどで削除します

f:id:am1tanaka:20180410171913p:plain

  • phaser.jsonを右クリック -> ファイル名の変更を選んで、jsdoc-ast.jsonにファイル名を変更したら[Enter]キーを押して確定します

f:id:am1tanaka:20180410172100p:plain

ここからはターミナルでの作業です。予め、こちらの記事に従ってPhaserのプロジェクトに対して、AtomでPhaserのコード補完が動くようにしておいてください。

  • LXTerminalなどのターミナルを起動して、Phaserのプロジェクトフォルダーへ移動します
  • 以下で、node_modules/tern-phaser/generator/nodeフォルダーへ移動します
cd node_modules/tern-phaser/generator/node
  • 以下を実行すると、Tern用のファイルが生成されます。
node ./make_plugin.js

f:id:am1tanaka:20180410175503p:plain

これで完了です。PhaserのプロジェクトをAtomで開いて、Packagesメニューから、Atom Ternjs -> Restart serverを実行すれば、最新版の情報でコード補完ができるようになります。

まとめ

Phaserは活発に開発されるため、頻繁に仕様変更やドキュメントの追加が行われます。こちらの情報が古いな、と思ったら、自分で更新してみてください。

関連URL


備忘録

以下、調査や以前の情報についての自分用のメモです。

続きを読む

AtomでPhaser3のコード補完をする

HTML5ゲームエンジンPhaser3のコード補完をAtomに組み込む手順をご紹介します。

(バージョンの変更に伴い、以前の同様のドキュメントは削除しました。)

目次

前提

  • Lubuntu16.04上での手順です。他のOSの場合は適宜読み替えてください
  • Atom( https://atom.io/ ), node, npm(あるいはyarn), gitがインストールされていること
  • Atom, gitが最低限使えること
  • Phaser3のプロジェクトフォルダーが作られていること
    • ない場合は、任意のフォルダーで、git clone git@github.com:photonstorm/phaser3-projet-template.gitを実行して、公式のテンプレートをクローンするとよいでしょう

gitコマンドで警告が出る場合...

Git - 最初のGitの構成を参考に、gitの設定にユーザー名とメールアドレスを登録してください。

AtomをTernに対応させる

まずは、AtomにTernjsの機能をインストールします。この作業は一度Atom上で実行していれば、それ以降は不要です。

  • AtomでPhaserのプロジェクトフォルダーを開きます(公式テンプレートなら~/phaser3-projet-templateフォルダー)
  • AtomEditメニューから、Preferencesを選択して、Settingsタブを開きます
  • Installをクリックして、検索欄にatom-ternjsと入力して検索します
  • atom-ternjsの欄にInstallボタンがあれば押して、インストールの完了を待ちます
  • SettingsやUninstallボタンが表示されれば完了です(最初からこの状態になっていたら、インストール済みなので、作業不要です)

f:id:am1tanaka:20180410134023p:plain

プロジェクトにPhaser用のternデータを読み込む

ターミナル(LXTerminalなど)で作業します。ここでは、Phaserのプロジェクトをphaser3-project-templateとして説明するので、別のプロジェクトだった場合は読み替えてください。

  • LXTerminalを起動します
  • 以下で、フォルダーを移動します
cd ~/phaser3-project-template
  • npm install(あるいやyarn install)を実行していなかったら、以下で実行します
npm install

あるいは

yarn install
git clone git@github.com:am1tanaka/tern-phaser.git node_modules/tern-phaser

ternの設定ファイルを作成

ternを有効にするために、設定ファイルを作成します。この作業はAtomで行います。TernはJavaScriptのファイルを開いている時のみ動作するので、まずはなんでもよいのでJavaScriptのファイルを開きます。

  • Atomに切り替えたら、srcフォルダーを開いて、index.jsを開きます(.jsファイルなら何でも構いません)

f:id:am1tanaka:20180410152643p:plain

Ternを設定します。

  • Packagesメニューから、Atom Ternjs -> Configure projectを選択します

f:id:am1tanaka:20180410151749p:plain

  • 設定ファイルが開くので、libs欄のbrowserにチェックを入れます

f:id:am1tanaka:20180410154528p:plain

  • 他にも、jQueryやUnderscoreなどを利用する場合は、それぞれの欄にチェックを入れると、それらについても補完できるようになります。よく分からなければ次に進んで構いません
  • 一番下のSave & Restart Serverボタンをクリックします

f:id:am1tanaka:20180410152845p:plain

以上で、プロジェクトフォルダー内に.tern-projectというファイルが出来上がります。それを開きます。

f:id:am1tanaka:20180410153332p:plain

  • 以下のように、11行目付近に"plugins"の属性に"phaser"を加えます
{
  "ecmaVersion": 6,
  "libs": [
    "browser"
  ],
  "loadEagerly": [],
  "dontLoad": [
    "node_module/**"
  ],
  "plugins": {
    "phaser": {},
    "doc_comment": true
    }
  }
}
  • 上書き保存します
  • index.jsなどのJavaScriptファイルを開きます
  • Packagesメニューから、Atom Ternjs -> Restart serverを選択します

f:id:am1tanaka:20180410153706p:plain

これで設定完了です。試しに、Phaser.と入力してみてください。以下のように、Phaserオブジェクトのメンバーが表示されるようになりました。

f:id:am1tanaka:20180410155007p:plain

表示されない場合は、Atomを起動し直してみてください。

以上で完了です。Visual Studioなどの高機能補完に比べると精度が低いですが、長いメンバー名を入力しなくて済むのは助かります。

まとめ

AtomでPhaserの補完機能が動くように設定しました。これで入力が随分楽になるはずです。ゲーム作りを楽しみましょう!

参考・関連URL

TernのJSON型定義ファイルのメモ

TernはJavaScriptの構造を解析して、オートコンプリートなどをしてくれるツールです。Phaserの最新版のTern用データを生成する際にエラーが発生して、解決策を知るために定義ファイルの仕様を確認したくなりました。これは、公式ドキュメントのTern Reference Manualを読んだメモです。

Ternは現在、開発が止まってしまっていて、Issuesが積み重なってしまっています。しかし、今のところ他の選択肢が見つかっていないので、できるところまではこれでやろうと考えています。クレジットカードがあれば、AWSのアカウントを取得してCloud9を利用する方がよいかも知れません。

目次

JSON type definitions

概要

Ternは、ソースコードを解析せずに型の特定するためのJSONデータフォーマットを持ちます。

型定義ファイルは、Objectのツリー構造をしています。最上位のオブジェクトがグローバルな変数を定義して、オブジェクトの型を定義するプロパティーをネストさせます。頭に!が付いているプロパティーは特殊な定義(Special directives)で、それ以外のものは通常の変数やプロパティー名の定義です。

以下、例です。

{
  "!name": "mylibrary",
  "!define": {
    "point": {
      "x": "number",
      "y": "number"
    }
  },
  "MyConstructor": {
    "!type": "fn(arg: string)",
    "staticFunction": "fn() -> bool",
    "prototype": {
      "property": "[number]",
      "clone": "fn() -> +MyConstructor",
      "getPoint": "fn(i: number) -> point"
    }
  },
  "someOtherGlobal": "string"
}

この定義にはグローバルな関数と変数が定義されています。MyConstructorコンストラクター関数を持ち、someOtherGlobalは文字列を持ちます。型や変数、プロパティーのoriginはmylibraryであり、!nameプロパティーで定義されています。

文字列による定義

変数やプロパティーの値は文字列とオブジェクトのいずれで持つこともできます。文字列では以下が利用できます。

  • number, string, booleanの組み込み型
  • fn(arg1: type1, arg2: type2) -> rettypeという関数型。-> rettypeは省略可能
  • [type]という配列型

文字列では、グローバルスコープにおけるパスでの指定(Date.prototype)や、+を頭に書いたコンストラクターインスタンス(+Date)を使うこともできます。

オブジェクトによる定義

オブジェクトによる型定義は、プロパティーを列挙して行います。デフォルトでは「単なるObjectインスタンス」として型定義されますが、!typeプロパティーを使うと、例のMyConstructorのように関数や配列の型を作ることができます。あるいは、!protoプロパティーを使って、カスタムのプロトタイプをオブジェクトに与えることもできます。

例:

"!proto": Element.prototype

ドキュメント

!docを使って、短文ドキュメントをアタッチできます。詳細ドキュメントについては、!urlで文書があるURLを指定するとよいでしょう。

関数の注釈(Annotation)

関数は注釈を表示することができます。defs/ecmascript.jsonから!effectsを探すと例を見ることができます。同様に、関数型の文字列は戻り値を表すことができます。!0は最初の引数型、!Nは(N-1)番目の引数、!thisは呼び出しの自己型、!retは関数の戻り値の型を返します。

参考URL