Ichizokuは日本唯一のSentry公認販売業者です。 日本語のドキュメント、動画、サポート窓口で日本のお客様のSentry活用を支援します。

【Unity開発】Sentry SDKを使用してパフォーマンスインサイトを有効にする方法

Sentry Unity SDKは、クラッシュの早期発見に効果的です。

以下をサポートしています。

  • IL2CPPのC# 例外での行番号サポート(リリースモードでも対応)
  • Windows、macOS、Linux、Android、iOSでのネイティブクラッシュのキャプチャ
  • C#を介して設定されたコンテキストは、ミニダンプを含むあらゆる種類のイベントに表示され、ゲームをエディターでビルドするときにデバッグシンボルが自動的にアップロードされる


私たちは、最良の『クラッシュ報告ソリューション』を提供していると確信しています。次に、ゲームのパフォーマンスに関する即座のインサイトを提供することを目標に掲げ、改良を進めていきました。

その中で、最初の問題に直面しました。
それは、Unityゲームの自動インストルメンテーションはどのようなものになるのか?という質問です。

SentryのパフォーマンスUXをUnityに適応する

Sentryはスパンツリーの可視化を提供しており、モバイルおよびWebのインストルメンテーションは画面レンダリングに基づいています。

これらの概念をUnityに適用すれば良いと考えました。
その結果、最初のインストルメンテーションをゲームのスタートアッププロセスとシーンの読み込みに絞り込みました。

すべてのゲームは必ず何らかの基点から始まり、どんなに大きなゲームでも小さなゲームでも、シーンを読み込む必要があります。

いまの段階では、ゲーム全体のインサイトを提供することは難しいですが、パッケージをインストールした直後にSentryが提供できるものをすべての開発者に示すことが可能です。

理想的なシナリオは、ユーザーからほとんど設定なしで即座に動作するものです。以下のスクリーンショットがそのプレビュー画面です。こちらが、Unity SDKの自動インストルメンテーションが提供する内容です。コードは一行も書かずに、すべてのUnityゲームで利用することが可能となります。


さらに興味深いのは、これをどのように構築したか、そしてそれがゲーム開発のパフォーマンスサポートの未来にとって何を意味するかです。
だからこそ、私たちはとてもワクワクしています。そして、開発者であるあなたもきっと興奮するトピックとなっているはずです。

【Unity向け Sentry SDK】マルチプラットフォームツール

Unityゲームは基本的にすべてのプラットフォームで動作します。
それをサポートするために、Sentry SDK for Unityは『SDKのためのSDK』になりました。ターゲットプラットフォームにネイティブなSDKとP/Invoke(FFI)を通じて統合され提供されます。

iOSで動作するのか?
もちろん。問題ありません。

Apple向けSentry SDKを含めてサポートします。また同様に、AndroidやネイティブのLinux、Windowsでも対応しています。

 

結局のところ、これがネイティブクラッシュキャプチャのサポートを実現した方法なのです。これらのSDKが共通して持っている特徴は、Unity SDKを支えるだけでなく、すべて自動インストルメンテーションを提供している点です。

しかし残念ながら、これは限られた利用範囲にとどまります。
Unityの成功の鍵となる要素はそのプラットフォームの抽象化です。

開発者はプラットフォーム固有の問題を気にすることなく、Unityの内部に集中できるメリットがあります。Unityゲームは通常、非常に薄いランチャー内に組み込まれているため、ナビゲーションイベントやUIアクティビティのような基盤となるプラットフォームの概念は、一般的に開発者には馴染みがありません。インストルメンテーションが、真に役立ち実行可能であるためには、SDKはUnity内で直接動作する必要があります。

 

【Unityライフサイクル】インストルメンテーションのための重要なポイントを見つける

ゲームは非常に高速なループで動作しており、通常は1秒間に30回から60回の更新を行いますが、上限はありません。

すべてのティックを測定するためにスパンを作成することは現実的ではありません。

私たちは、キャプチャしたい論理的な操作のセットなど、いくつかの主要なアクションに注目する必要がありました。

トランザクションとスパンを定義する課題

Sentryには、何かがどれくらいの時間を要するかを測定するための2つの概念があります。それは「トランザクション」と「スパン」です。

トランザクションは、ページの読み込みや非同期タスクのような、活動やサービスの単一のインスタンスのことをいいます。

スパンは、トランザクション内でネストされた個別の測定値のことです。

概念的には、私たち開発者は、測定したい特定のアクションに対して、巨大なストップウォッチを使って開始と終了の場所を見つけようとしています。
そして、そのアクション内で小さなストップウォッチでキャプチャできるサブタスクを探しています。

しかし、トランザクションはゲームのフレームワーク内でどのように適合するのでしょうか?
ゲームエンジンにすでに組み込まれているサービスのインスタンスが、どのようにトランザクションとして表現されるのでしょうか?

Unityはそのすべての機能にもかかわらず、あらゆる種類のゲームを作成するための真っ白なキャンバスです。
つまり、一般的なライフサイクルを除けば、SDKがスパンを開始および終了するためにフックできる固定されたポイントはあまり多くありません。ボタンのクリックなど、ワンタイムのイベントはたくさんありますが、SDKはボタンクリックの背後で何が起こっているかにどうフックするのでしょうか?
SDKは、スパンを終了するタイミングをどう判断するのでしょうか?

スタートアップとシーンの読み込みのタイミングを測定する

すべてのゲームは起動する必要があり、スタートアップ手順はすべてのUnityゲームで共通です。

システムの読み込み、スプラッシュスクリーン(適用される場合)、そして最初のシーンの読み込みから成り立っています。

シーンの読み込みは一般的に、もう1つの優れた固定ポイントです。
Unity内のすべてはシーンのコンテキスト内で存在します。
いくつかのゲームはシーンを追加で読み込み、いくつかのゲームはシーンを入れ替え、いくつかのゲームは1つのシーンしか持たない場合もあります。しかし、少なくともその1つのシーンはスタートアップ時に読み込まれます。

これにより、私たちはトランザクションのフックを得ることができます!
スタートアップが開始され、終了するタイミングが明確になります。

また「シーンマネージャ」にフックして、シーンの読み込みと、シーンの読み込み終了イベントのタイミングを測定することもできます。

トランザクションにスパンを追加し、粒度を細かくする

大きな操作が明確になったので、次はシーン読み込み時に発生する小さなアクションに着目します。

再び、Unityのライフサイクルを見てみましょう。初期化は、すべてのGameObjectでその作成時に発生します。もしそのGameObjectがシーンの初期部分であれば、シーンの読み込み中に初期化されます。すべてのGameObjectに共通するメソッドはAwakeコールです。そしてそれがユーザーのコードであり、まさにインストルメンテーションしたい部分です。

これがユーザーが制御するコードで、パフォーマンスの機会やボトルネックを強調したい場所です。しかし、SDKがユーザーに頼まずに、非SDKコードをどうインストルメンテーションするのでしょうか?

中間言語(IL)の織り込み

Unityゲームの開発では、通常C#を使用してコードを書きます。その後、IL2CPPを経由してプラットフォームのネイティブコードにコンパイルされますが、ビルドプロセスのどこかでそのC#コードは中間言語(IL)にコンパイルされます。Unityは後でそのILをC++にトランスパイル(異なるプログラミング言語間でコンパイルする際に使用するプロセスのこと)するかもしれませんが、そのILはどこかに残っています。

私たちは、SDKをビルドパイプラインにフックして、生成されたAssembly-CSharp.dllを修正することに成功しました。

デモンストレーションのために、非常にシンプルなMonoBehaviourを例として見てみましょう。以下に示します。

このMonoBehaviourは、次のようにコンパイルされます。

Cecilを使用してコードを生成する

私たちは、Awake内で行われていることをスパンでラップしたいと考えています。そのために、ユーザーのコード内のどこからでもアクセスできるヘルパーを作成しました。

最初はこの変更を手動で行い、その結果得られたIL(Intermediate Language)を確認しました。

しかし、.dllは単なるテキストファイルではありません。

それでは、これをどのように修正するのでしょうか?
幸いなことに「Cecil」というライブラリがあり、これを使うことで簡単に修正することができます。Cecilは、まるで数字で塗り絵をするかのようにこれを処理します。

1. コードをコンパイルして「ベースライン」を作成する
2. ソースコードを修正して、目的の最終結果にする
3. コンパイラに得意分野を任せ、C#コードをILに変換させる
4. ベースラインと最終結果の違いを確認する
5. Cecilを使って変更を再現する

Awakeを修正し、StartSpan機能を追加するコードは以下のコードです。

こちらで、ILの読み込み、修正、および書き込みのセットアップ全体を確認できます。

その結果、ユーザーが一行のコードも書かなくても、すべてのUnityゲームに対してこのトレースビューが提供されます。

 


現在、私たちが達成していること

このIL織り込みセットアップにより、次の2つの目標を達成しました。

  • 即時的で視覚的なパフォーマンスの価値
    開発者は追加のコードを記述することなく、自己インストルメンテーションされたパフォーマンスインサイトを閲覧可能とすること
  • 将来の拡張のための基盤
    ユーザーコードをラップするカスタムSDK機能を注入することが可能であることを証明し、将来的な自己インストルメンテーションの機会を提供すること
ぜひ SentryのUnity SDK をお試しください

このセットアップにより、さらに多くのインストルメンテーションの可能性が開かれます。例えば、UnityWebRequestの自動インストルメンテーションや、ボタンクリックの周囲でアクションを計測してスパンを追加することも考えられます。

Unityでゲームを開発している方。
ぜひUnity SDKを試してみて、GitHubDiscordでフィードバックをお気軽にお送りください。

快適な開発ライフが待っています!

 


 

IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。

シェアする

Recent Posts