[UEFN][Verse]logクラスを使って失敗コンテキスト内でもコンソール出力デバッグを可能にする
イベント実装の続きを書いているのですが、このスニペット[1]を見て「logクラスなんてあったの!?」と驚いたので記事にまとめました。
logクラスとは
Verseはサーバーサイドで実行されている事もあり、現状ではステップ実行する方法がありません。その為、デバッグは主にPrint()関数を使う原始的な方法で行う必要があります。
ところが、Print()メソッドは<no_rollback>
が指定されていて、失敗コンテキスト内では実行する事ができません。例えば、if式の述語部で複数の条件を記述した時、どの条件で失敗したのかをPrint()で確認するとうい事が出来ないのです。
ではどうするのかというと、Print()メソッドの代わりに、ログの仕組みを使用します。ログはPrint()メソッドと同じようにコンソールに文字列を出力する仕組みで、かつ、<no_rollback>
の制限がありません(どうしてPrint()ではNGでログではOKなのかはよくわからない)。
ログはlog
/log_channnel
/log_level
の3つのクラスで構成されます。
サンプルコード
サンプルコードは以下にになります。
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
#A:ログチャンネル定義
my_log_channel<public> := class(log_channel):
log_test := class(creative_device):
@editable MyButton : button_device = button_device{}
#B:ログ出力
ProjectLog<public>(Message:[]char, ?Level:log_level = log_level.Normal)<transacts>:void=
Logger := log{Channel := my_log_channel}
Logger.Print(Message, ?Level := Level)
OnBegin<override>()<suspends>:void=
#ボタンにイベントハンドラを登録
MyButton.InteractedWithEvent.Subscribe(HandleButtonInteraction)
#C:ボタンがインタラクトしたら実行される
HandleButtonInteraction(Agent : agent) : void =
if:
ProjectLog("log_level.Normal")
ProjectLog("log_level.Warning" , ?Level := log_level.Warning)
0=0
ProjectLog("log_level.Error" , ?Level := log_level.Error)
then:
Print("Success")
else:
Print("Fail")
log_test
デバイスをシーンに配置し、詳細タブでボタンを設定します。ゲームを開始してボタンにインタラクトすると、コンソールに以下の様に出力されます。
最初の3行が、log出力された文字列になります。
コード解説
主要な処理について解説します。
#A:ログチャンネル定義
my_log_channel<public> := class(log_channel):
ログ出力する場合、そのログが属するチャンネルを設定する必要があります。ログチャンネルは、log_channel
クラスを継承したクラスとして定義します。ここではmy_log_channel
ログチャンネルを定義しています。ちなみにですが、行末の":"を忘れると構文エラーになるのでご注意ください。
#B:ログ出力
ProjectLog<public>(Message:[]char, ?Level:log_level = log_level.Normal)<transacts>:void=
Logger := log{Channel := my_log_channel}
Logger.Print(Message, ?Level := Level)
ログ出力するメソッドです。logクラスはアーキタイプでmy_log_channel
をログチャンネルに指定しています。log#Print
メソッドにはlog_level
列挙体を使って、ログのレベルを指定できます。
log_level
列挙体は現状5個のレベルが定義されていますが、機能するのはNormal
/Warning
/Error
の3個のみのようです[2]。
#C:ボタンがインタラクトしたら実行される
HandleButtonInteraction(Agent : agent) : void =
if:
ProjectLog("log_level.Normal")
ProjectLog("log_level.Warning" , ?Level := log_level.Warning)
0=0
ProjectLog("log_level.Error" , ?Level := log_level.Error)
then:
Print("Success")
else:
Print("Fail")
ここでログを出力しています。途中で0=0
という式が入っていますが、これはif
式の中には最低でも一個は失敗許容式が必要な為です。この式を0=1
に買えて再実行すると、出力は以下の様に変化します。
先程と異なり、ログは2個しか出力されず、順番も逆で、かつ文中に"(Rolling Back)
"と書かれています。これは、0=1
が評価されたタイミングでif
式が失敗し、処理が(実行順と逆順に)ロールバックされた事を示しています。これにより、if
式が失敗したのが3つめのProjectLog()メソッドの直前、つまり0=1
のタイミングであると分かるわけです。
終わりに
土屋自身はそこまで複雑なif式を書いていないので、このようなログ機構が必要になった事はまだ無いのですが、ログレベルの指定も出来ますし、覚えておくと便利なのではないでしょうか。多分。
お知らせ
verse言語とUEFNの記事を他にも書いているので御覧下さい。
最後まで読んで頂きありがとうございました。この記事がお役に立てたようであれば、是非LIKEとフォローをお願いします(今後の執筆のモチベーションに繋がります)。
#Verse #UEFN #Fortnite #Verselang #UnrealEngine
Discussion