UnityでAssertを使うときに覚えておきたい2つのこと

Unity

http://kan-kikuchi.hatenablog.com/entry/Assert
Unityには標準でアサーションクラスが定義されています。
これはdevelopment buildのチェックを外すと製品版から取り除くことができる優れものです。
防御的プログラミングとしてアサーションを積極的に使っていることでしょう。

しかしUnityのこのアサーションクラスを使うときに気をつけなくてはいけないことが、いくつかあります。
それを見ていきましょう。

Assertの第二引数は必ず評価される

どういうことかというと

SpriteRenderer sprite = null;
Assert.IsTrue(true, sprite.name);

このAssertは常に正なのでアサーションは発生しません。
にもかかわらず第二引数であるsprite.nameは評価され、null errorが発生します。
これ、意外と引っかかります。
そのため第二引数部分は、どんな時でも正常に動作するコードのみ書かなくてはいけません。

Assertはラップして使う

次のコードを見てください。

void Update()
{
Assert.IsNotNull(hogehoge, "hogehoge is null =" + Time.frameCount);
}

hogehogeがnullだったらアサーション発生というごく普通のコードです。
ところが第二引数は必ず評価されます。
この処理は動的にstringインスタンスを生成するためgcallocが発生します。
さらにUpdateで毎フレーム呼び出されるため、毎フレームgcallocが発生します。
これが致命的で、無駄なgcallocのせいでパフォーマンスの正確な計測が難しくなります。

development buildのチェックを外すことでアサーションを無効化できますが、今度はprofilerが使えなくなるのでパフォーマンスチェックできません。

PlayerSettingsのLoggingでAssertをNoneにしても呼び出しはされるため結局gcallocされます。 対策としては

  • if文で囲う
  • 自前Assertを作る

UnityのAssertクラスをラップして自プロジェクト用のMyAssertクラスを作ればよいのです
http://d.hatena.ne.jp/nakamura001/20151202/1449029637
[System.Diagnostics.Conditional(“USE_ASSERT”)] を設定し、USE_ASSERTデファインを無効にすればAssertの呼び出しそのものを無くすことができます。

まとめ

上記以外にも、そもそもアサーションをどこに使うべきか、という悩みもあります。
あらゆるところにAssert.IsNotNullを仕込むのが適切かといえば、違います。
ガイドライン的なものに関しては、長くなるので他の書籍にゆずります。

MicrosoftのCode Completeは一番のオススメです。
アサーションを使うためのガイドラインについて、具体例をまじえて分かりやすく説明しています。

契約による設計という開発手法における、事前条件・事後条件のためにアサーションを使うことを説明しています。
この本は理論中心でかなり難しいです。
しかし理論を学んだうえでの実践は、習熟度が圧倒的にあがるので読んでみることをおすすめします。