Unity を検索

Unityのアサート機能について

2015年8月25日 カテゴリ: テクノロジー | 4 分 で読めます
取り上げているトピック
シェア

Is this article helpful for you?

Thank you for your feedback!

Unity 5.1 では新しくUnityにアサート機能を提供する Assertion ライブラリが提供されました。この記事ではアサートとは何か、この機能をどう使えばゲーム実行時のエラーからより多くの情報を取得して問題解決に繋げられるかをお話しします。

アサートって何?なぜアサートを使った方がよいのか

アサートとはザックリ言うと特定の条件が成立しているかどうかをチェックするための機能です。もし条件が成立(trueを返)していれば、アサート関数はなにもせずにゲームは通常どおり進行します。しかし何かが起きて期待している条件が成立しなくなると、アサート関数はメッセージとコールスタックを表示します。え、ピンと来ない?それじゃあ、さっそく具体例を見てみましょう:

//プレイヤーのGameObjectは必ずactiveであること
Assert.IsTrue(playerGameObject.isActive, “Player GameObject is not active”);

この例では、参照しているゲームオブジェクト(GameObject)がアクティブでなかった時に、あらかじめ設定しておいたエラーメッセージ“Player GameObject is not active”と発生時のコールスタックがエラーログメッセージとして出力されます。

Assertion message

多くの開発者はアサートをユニットテストで学んでいます。単体テストを記述するための一般的な方法である Arrange-Act-Assert (AAA) パターンを使ったユニットテストの実装では、アサートの利用は最後の部分である結果の比較に利用します。しかしアサートは短にテストのための機能ではありません。実際のゲームのコードにも使用する事で、ゲームの実行時に何かおかしな事が起きたら早めに分かるようにすることが可能です。とはいえ、すべてのアサート機能がゲームのコードに使われるべき、というわけでもないのです。

ユニットテスト・フレームワーク由来のアサート機能

アサートにはじめて出会ったのがユニットテスト・フレームワークだという人は結構多いのではないでしょうか。ユニットテスト・フレームワークというのは、たとえばNUnitなどです。NUnitは充実した機能を持ちつつも実戦で鍛えられたアサート機能のライブラリを備えており、それを使ってテストを書くことが出来る優れものです。「え、じゃあもうゲーム開発でもそれを使えばいいじゃない?」…そう思われるのは自然な流れですが、NUnitが適切でない理由がいくつかあります。一番大きな理由を一言でまとめると「そういう目的で作られてないから!」この一点に尽きます。

NUnitのアサート機能はさまざまな事柄をテスト可能にしてくれます。単純な等値性の比較から、もっと複雑な処理のはてに例外を投げるようなものまで多岐に渡ります。これはありがたい機能なのですが、実際のゲームコードで利用するには少々遅すぎるのです。ゲームコード用に使えるアサートはできる限り無駄を廃したコードで、実行時の負荷を極限まで下げる必要があります。UnityのAssertionライブラリは不要なメモリ確保や無駄な処理を一切行わないよう注意深く実装されています。

もう一つ、ゲーム用のAssertionライブラリは、そのメソッド呼び出しをリリースビルドの時に完全に除去することが可能になっているべきです。アサート機能は開発中は便利ですが、例え(アサートに失敗して)問題を捕捉してもエンドユーザーには何の価値もありません。ですので、最終的な製品向けプログラムのビルドではアサート処理は取っ払ってしまいたいと思われるでしょう。論理的には全部のアサート処理をコメントアウトする方法もあるでしょうが、あまり頭のいい方法ではありませんよね。幸運な事に.NETは、こういうときのために条件コンパイルのメカニズムを有しています。AssertionライブラリはConditionalアトリビュートをもっているので、アサート処理は開発用(development)ビルドでのみ含まれるようになっています。しかしながら、もし望むのであれば、コンパイルオプションを明示的に設定することで強制的にAssertionを有効にすることも可能です。

最後に、通常のユニットテスト用ライブラリのアサート処理は例外を投げることを前提に設計されています。例外が投げられると、当然ですが処理の流れが変わってしまいます。これはゲームコードからすると望ましい状態ではありません。代わりに、AssertionライブラリはUnityのログシステムと統合されており、メッセージは例外ではなくログに記録される形になります。この変更によりライブラリを全てのプラットフォームで幅広い用途で利用出来るようになります。さらにこの方針は例外をサポートしていないAOT(Ahead-Of-Time Compile, 事前コンパイル方式)ベースのプラットフォームでも利用出来るメリットがあります。

UnityのAssertionライブラリに含まれるもの

UnityのAssertionライブラリはいくつかの型に特化した比較メソッドと一般的な等値性比較クラス(Comparer)を有しています。いくつかの機能を紹介しますと:

  • AreEqual - 一般的な等値性のアサートに使われるメソッドです。デフォルトの等値性比較用Comparerで比較されます。
  • AreApproximatelyEqual - 計算エラーの揺らぎを許容した近似比較メソッドです。小さな計算誤差の出る浮動小数点数の比較などに便利です。
  • IsTrue - 手早く簡単なブーリアン比較に使えるメソッドです。

その他、ライブラリの全機能はAssertのドキュメントを参照してください。

このライブラリのいいところは、Unity Test Toolsとの完全な互換性を保っていることです。特に追加の努力をなにもしなくても、アサートはUnity Test Toolsから呼ばれた結合テストで適切に失敗します。

Assertionライブラリを拡張する

Assertion機能をぞんぶんに活用したいと思う時、これを拡張したいと思うのは自然なことです。簡単で機能的な方法として、AssertionライブラリのAreEqualメソッドは特定の型について開発者が独自に比較クラス(Compararer)を実装して渡すことが出来るようになっています。比較機能を新たに実装する場合は IEqualityComparer インターフェイスを利用します。

たとえば、ライブラリは浮動小数点数を比較するために内部的にIEqualityComparerfloat>を実装した FloatComparer というクラスを作成し、AreApproximatelyEqual で利用しています。

まとめ

Assertionライブラリはすぐに利用可能ですので、これを活用してゲームのコード上の意図しない状態を発見しやすくして、あなたのコードをバグから守りましょう!Assertionライブラリの機能は今後も改善していきますが、みなさんからのフィードバックやご提案も積極的におまちしています!

2015年8月25日 カテゴリ: テクノロジー | 4 分 で読めます

Is this article helpful for you?

Thank you for your feedback!

取り上げているトピック