[UE4] ensureを使おう！

UE4にある便利マクロ、ensure関係についてまとめてみました。
開発の上でお役に立てれば幸いです。
なお、エディタはVisualStudioを使っている想定で書いています。

# ensureってなに？ #
UE4に定義されているアサーションマクロの一つです。
基本的な機能としては、実行呼び出されると **ブレークを発生させて実行を中断させる** 事ができます。
致命的ではないエラーの場合に使います。

公式ドキュメントがこちら
・[UE4 アサーション](https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/Assertions/)

### ensureの機能 ###
・VisualStudioなどでデバッグ実行中の場合、ブレークを発生させて実行中断します。
・実行中断された状態からF5などを押すとプログラム実行を継続できます。（強制終了しない）
・呼び出された場所のコールスタックをログに書き出します。
・デバッグ実行中でない場合（スタンドアロンなど）は[クラッシュダンプ](https://e-words.jp/w/%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%80%E3%83%B3%E3%83%97.html#:~:text=%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%80%E3%83%B3%E3%83%97%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF,%EF%BC%88crash%20dump%EF%BC%89%E3%81%A8%E3%82%82%E8%A8%80%E3%81%86%E3%80%82)を生成します。

一言でいうと、**コードのエラーが発生する箇所に直接記述する[ブレークポイント](https://e-words.jp/w/%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88.html#:~:text=%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF,%E6%8E%A2%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E7%94%A8%E3%81%84%E3%82%89%E3%82%8C%E3%82%8B%E3%80%82)** です。

### 記述例 ###
```
ensure(checkCount == 0); // 評価式がfalseの場合に発生.
eusure(false); // 呼び出されると無条件で発生.
```

### checkとの違い ###
UE4には同じ種類のマクロとしてcheck系がありますが、ensureとcheckは機能に違いがあります。

:::note info
checkとensureの大きな違い
・check  は呼び出されるとブレークを発生させて <b>プログラムを強制終了する</b>
・ensure は呼び出されるとブレークを発生させて <b>そのまま実行を続けることができる</b>
:::

checkの挙動はC++にあるassertと同様の機能です。
ensureは一度実行中断はされるものの、そのまま継続してプログラムを実行し続けることが可能です。

# ensureのメリット #

### プログラムを実行し続けられる ###
ensureを使うメリットは、なんと言っても **プログラムを実行し続けることができる** ことです。
checkマクロはプログラムを強制終了してしまうため、呼ばれるとつまり **UE4エディタが落ちてしまいます。**

ゲーム開発では繰り返しプレイすることがあったり、パラメータをデバッグ機能などで書き換えながらプレイすることも多いです。
例えばcheckが呼び出されてエディタが終了してしまった場合、**エディタを起動し直してまた最初からプレイをし直す**事になってしまい、確認に時間がかかってしまうことになります。

もちろん、プレイを継続させると問題があるようなクリティカルなエラーはプログラムを終了させるべきです。
ただ、ensureも使うことで、なにか問題がある処理が実行されたことをわかりやすくでき、かつエディタと落とすことを防ぐことができます。
プログラムの実行終了をさせるほどでもないが問題が起きたことをわかりやすくしたい、といった場合にensureを使うとメリット高いです。

### ブレークポイントをおかなくもブレークできる ###
プログラマからのメリットとしては、ブレークポイントを手動で設定する手間を省略できるのがメリットかと思います。
あらかじめ止めたい場所がわかっている場合にはensureを記述しておくと、直接ブレークポイントをコードに書いているようなもののため設定の必要がないです。
例えば呼ばれるはずのない想定外の箇所などに記述しておくと、プログラマに想定外の挙動などを伝えやすくなると思います。

他のメリットとしては、
・**コードに記述できるので複数人のプログラマにブレークポイントを共有できる**
・**ブレーク条件もコードに記述して設定できるのでやりやすい**
ということもあるかと思います

### ログメッセージ出力よりも気づきやすい ###
ログを出力だけして実行を続ける、というのもよくやることかと思います。
ただ、ログは見逃されやすいです。

UE4エディタではログメッセージをWarning,Errorといったカテゴリ分けで文字色を変えたりもできます。
また、プレイ画面にもメッセージを出すこともできます。
ただ、ログウィンドウをずっと見ていないといけなかったり、フィルタを掛けてエラーメッセージだけ表示などでわかりやすく工夫しないとログに埋もれたり、プレイに集中してたりするとなかなか気づきづらいと思います。
その点、ensureは呼び出されると実行が止まるため、とくにプログラマに問題が起きたことをわかりやすく伝えることができます。

デバッグ実行していない場合でも、ダンプファイルを生成している間すこし **アプリケーションが固まる** ため、なにか変な事が起きたと気づくきっかけにはできます。


# ensureのデメリット #
プログラムを強制終了させないとはいえ、呼び出される頻度が多すぎるとプレイに支障がでると思います。
ensureを仕込みまくったりはせず、場所を考えてログメッセージなどと併用して使うことは必要そうです。


# ensureの種類 #

ensureマクロには全部で **4種類** あるようです。
・ensure
・ensureMsgf
・ensureAlways
・ensureAlwaysMsgf

### ensureとensureAlwaysの違い ###
:::note info
・ensureはプレイ中に呼び出されると <b>一度だけ</b> 機能する
・ensureAlwaysはプレイ中に <b>呼び出されるたびに</b> 機能する
:::
エディタを立ち上げた状態で何度もプレイしている場合に挙動に差があり、ensureは2回目以降に呼び出されてもなにも起きないですが、ensureAlwaysの場合は呼び出されるたびに機能します。

### ensureとensureMsgfの違い ###
:::note info
・ensureMsgは呼び出された際に出力する任意のログメッセージを記載できる
・ensureはログメッセージは記述できない
:::
呼び出されたと同時に出力する任意ログメッセージを指定できるかが違いです。
printf同様にフォーマット文字列が使えます。
ensureAlwasyとensureAlwaysMsgfの違いも同様です。

# UE_DEBUG_BREAK #
ensureと似たような機能のマクロとして、UE_DEBUG_BREAK()もあります。
こちらはシンプルなブレークポイント機能で、ensureと違ってコールスタックもダンプファイルも出力しません。
エラーではなくただブレークしたいだけなら、こちらを使うというのもありかと思います。

## まとめ ##
ensureを適切に使うと開発が楽になる部分や問題も見つけやすくなると思います。
checkマクロやログ出力と合わせて使っていくのがおすすめです。