VisualScriptAction デバッガ、改善提案

AGM API への最初の「ハック」です。

ビジュアルスクリプトのデバッグはすでに煩雑になりそうな予感がしますし、PrintMessageToConsole アクションを追加するのは手間がかかります https://guild.rpgmakerofficial.com/t/topic/197

より良いのは、VisualScriptAction に直接デバッグを有効にするオプションを設けることです。

これは 1.0.6 や 1.0.7 での実装を求めているわけではありません。まだアイデアとして洗練が必要です。ビジュアルスクリプティングで実現可能な他のデバッグ機能についても検討しています。

本来はオプションの表示場所を示す画像だけの予定でしたが、ツールコーダーがデモスクリプトを作成してしまいました。

GitHub Gist: Action Game Marker, Visual Script debugging, GDScript tools

元のスクリプト

# debug_vsa.gd
extends VisualScriptAction

@export var print_message_to_console : bool = true :
	set(v):
		if v:
			_add_print_action.call_deferred()
		else:
			_remove_print_action.call_deferred()
		print_message_to_console = v

var _print_action : Actions = PrintMessageToConsole.new()
var _print_action_at_index : int

func _init() -> void:
	_print_action.print_message = visual_script_node_title + " entered"

func _add_print_action() -> void:
	other_actions.append(_print_action)
	_print_action_at_index = other_actions.size() - 1
	
func _remove_print_action() -> void:
	if  other_actions.size() > 0 and other_actions[_print_action_at_index] == _print_action:
		other_actions.remove_at(_print_action_at_index)

(現在、.gd スクリプトはファイルタイプとしてアップロードできません)

このスクリプトのランタイムにおける _remove_print_action() は未検証です。

Godot スクリプティングに精通した上級者の方向けに、既存の VisualScript (VS) 内の State にこのスクリプトをアタッチする方法を以下に示します。

  1. FileSystem に debug_vsa.gd を作成します。
  2. VisualScriptAction を継承している必要があります。そうでない場合は…
  3. 上記のスクリプト全体をコピーします。
  4. 既存の VS を作成するか、既存のものを使用します。
  5. Initial State を選択します。
  6. インスペクターで一番下までスクロールし、‘RefCounted’ ヘッダーまで移動します。
  7. debug_vsa.gd をロード、クイックロード、またはドラッグして割り当てます。

これで「Print Message to Console」のチェック済みブール値が表示されるはずです。テスト実行では、State の名前と「entered」を含む出力メッセージが表示されます。

デバッグにおいて非常に役立つのは、Godot 用の SignalVisualizer プラグインのようなものです。どのリンクや State がトリガーされているかを視覚的に追跡できるようにするためです。

デバッグを超えて、VisualScriptActionVisualScriptActionLink を拡張しても、実際のビジュアルスクリプトインタプリタへのエントリーポイントが提供されるわけではない点に注意してください。これらは単に AGM が事前に定義された条件チェックを行い、事前にスクリプト化されたコードを実行するために使用する Resource です。

これらにより、カスタム GDScript を介して特定のリンクや State、その ConditionsActions を簡単に修正できるようになる可能性があります。現在のプロセス安全性については不明な点もあるため、AGM がすべての VS リソースを参照して修正する前に変更を加えることができるよう、_physics_process から call_deferredset_deferred を使用することを検討してください。

「いいね!」 3

GitHub Gistへのリンクを追加しました。これはオプションをテストする際に更新を受け取るためのものです。

PrintMessagetoConsoleの使用は優雅ではありません。深刻なトレースに必要な情報が不足しています。

デバッグ出力は、何かが間違っているかどうかだけでなく、どこで正確に問題が発生しているか(GameObjectインスタンスとLink/State)を、あるいは問題の場所を近くで見つけるのに十分な情報を提供できるはずです。

おそらくより良い解決策は、Linksが自らのConditionsを中央のDebuggerに登録する仕組みを作ることです。これにより、Debuggerは監視すべきものを認識できるようになります。最低限、GUIを作成して、どのLinksがトリガーされるべきだったかを調査できるようにすることも可能です。これは、他の場所で観測可能なパラメータに基づいて行われます。

「いいね!」 1

有効 1.0.2 – 1.0.4

VisualScript (.vs) は GDScript で変更可能です。VisualScript は、load(res://path/to/visual_script.vs) で直接読み込むか、既存の GameObject に対して Object get_script を使用してアクセスできます。

VisualScriptActionLink(リンク)および VisualScriptAction(状態)への参照は、VisualScript.get_node(id:int) を使用して取得できます。

クラス継承

  • リソース // Godot クラス
    • VisualScriptNode // AGM クラス
      • VisualScriptAction // 状態
      • VisualScriptActionLink // リンク

VisualScript
メソッドの説明

  • VisualScriptNode get_node(id: int)

VisualScript のデータに含まれる VisualScriptNode への参照を返します。これは VisualScriptAction(状態)または VisualScriptActionLink(リンク)のいずれかになります。GDScript ではキャストは不要です。Godot のメソッド Node.get_node() とは異なります。

  • bool has_node(id: int)

このインデックスに有効な VisualScriptNode が存在する場合は true を返し、それ以外は false を返します。

配列やその他のコレクションは直接アクセスできません。値は連続して保存されていない場合があります。一部のインデックス値は null になる可能性があります。VisualScript 内のすべての VisualScriptNode の完全なリストを取得するには、get_node メソッドをループ処理する必要があります。

#GDScript

var vscript #game_object.get_script() または load("res://path/to/visual_script.vs")

# Typed Dictionaries は Godot 4.4+ へのエンジンアップデートまで利用できません
var states: Dictionary #[int,VisualScriptAction]
var links : Dictionary #[int,VisualScriptActionLink]

# 保存される VisualScriptNode の最大数は不明ですが、
# 1 つのスクリプトに 1000 のリンクと状態があるのは過剰と思われます。
# 配列であると仮定し、`id` は 0 未満にはならないと推測します。
for i in range(0, 1000):
\t\tif !vscript.has_node(i):
\t\t\tcontinue # 次のインデックスへスキップ
\t\tvar n = vscript.get_node(i)
\t\tif is_instance_valid(n):
\t\t\tif n is VisualScriptAction:
\t\t\t\tstates[n.id] = n # KEY id : VALUE VisualScriptAction 参照
\t\t\tif n is VisualScriptActionLink:
\t\t\t\tlinks[n.id] = n # KEY id : VALUE VisualScriptActionLink 参照

状態とリンクにはアクセス可能なプロパティがあります。これらは Filter Properties :hammer_and_wrench: ボタン(右側)を使用してインスペクタで確認できます。

VisualScriptAction の場合、other_actions 配列には Actions リソースが含まれています。

デバッグ用途として、現在 PrintMessageToConsoleEmitSignalInitializeObject、および ChangeAction アクションを検討しています。

現在、VisualScript のロジックと実行を固定する何らかのコンパイル処理が行われています。これは GameObject が初期化されるタイミング(正確なタイミングは現在調査中)で行われます。初期化後に追加された VisualScript への変更は、既にインスタンス化された GameObject には適用されませんが、新しいインスタンスには適用されます。

これにより、ランタイム中にデバッグシステムを有効化することが複雑になります。

InitializeObject アクションは、既存の GameObject のロジックを更新し、新しい Actions を追加します。InitializeObject は、一部の GameObject で使用すると不安定(ランタイムクラッシュ)です(現在調査中)。

PrintMessageToConsole は、GameObject が InitializeObject された後に機能し始めます。デバッグ用には、print_messageTimeNodeAction に関する情報を含めるように設定する必要があります。@GlobalScope.print_rich() を使用した PrintRichToConsole があれば役立つでしょう。

EmitSignal アクションは現在、正常に動作していません。GDScript から other_actionsEmitSignal を追加すると、GameObject に新しいシグナルが追加されます。これは Object.has_signal("signal_name") で確認できます。GDScript で connect() および emit() を実行できます。残念ながら、InitializeObject 後であっても EmitSignal アクションは emit() をトリガーしません。これは現在、デバッグには機能していません。

ChangeAction および ChangeObjectProperty は、機能しない EmitSignal の代替手段として可能です。“デバッガ” GameObject の状態を、必要なデバッグ情報を含むプロジェクトデータベースの record を送信する事前作成された EmitSignal を持つ状態に強制的に変更します。これは、より堅牢な GDScript ベースのデバッガに接続されるべきです。これは現在、未テストです。

「いいね!」 1

現時点で私が思いつく最善のアイデアは、デバッグが必要なビジュアルスクリプトを事前に読み込むためにGodotのオートロードを使用することです。CoreScene.tscnが読み込まれる前にそれらを変更します。そして、PrintMessageToConsoleChangeAction+ChangeObjectPropertyの追加が定着することを願います。

本当に役立つのは、GameManagerに何らかのデバッガーがあることです。ビジュアルスクリプトの実行の設計については知らないため、二重のboolチェックという大まかな提案しかできません。これはVisualScriptNodedebugプロパティのチェックボックスを追加することと併せて行います。

if GameManager.debugger_on && current_node.debugger_on:
    GameManager.debugger_signaled.emit(current_game_object, current_node)

これをC++でより良い方法で設定する方法が間違いなくあり、ビジュアルスクリプトの各ステップでデバッガーが非アクティブかどうかをチェックする必要はありません。

GameObjectと現在のVisualScriptNodeを渡すデバッガーシグナルがあれば、サードパーティのデバッガーがGUIを構築するのに十分な情報になるはずです。

Inspector でユーザーがいくつかのオプションを有効にして、コンソールにより詳細な情報を出力できるようにすることは良いアイデアだと感じます。もしかすると、この件をより明確に整理し、公式にこの機能をサポートすることもできるかもしれません。

どのフィールドオプションを提供し、どのような内容を出力すべきかについて、何かご提案はありますか?比較的明確で実現可能な提案があれば、これらを実装する絶好の機会だと考えられます。これらの機能は、過度に複雑なインタラクションを導入するものではなく、開発中に非常に便利だからです。

非視覚的なコードでは、breakpoints(ブレークポイント)を設定できます。これにより、コードの実行が一時停止し、デバッグを行っている人が現在の実行位置を確認し、監視されている変数をチェックできるようになります。

  • LinksStatesActions の実行を監視
  • LinksStatesActions にブレークポイントを設定
  • 特定の GameObject プロパティやデータベースレコードを監視
    • Baz が Discord の英語版ショーケースに例を投稿しました
  • GameObjects の現在の State を監視

デザイナーにとって使いやすいツールは、これらの情報を一元化して表示する GUI を作成することです。

  • デバッグ用の Links は、その Conditions(条件)を提供できます
  • Conditions は、監視すべきプロパティやユーザー入力を提供します
  • デバッグ用の States は、いつ実行されたか、および意図したアクションが何かを報告すべきです
  • アクションは、その引数設定を、より読みやすく共有しやすい形式で報告します

これらは、以下のような最も一般的な質問に対する答えを提供する上で非常に役立ちます。

なぜこれが機能しないのですか?

これは、デザイナーがより直接的な質問を始めるための知識ツールを持っていない場合に、公的に問われることです。

  1. なぜ特定の State やコードセクションが実行されないのですか?
  2. なぜこの StateAction が望んだ動作をしないのですか?異なる動作をしています。

最初の質問は、必要な条件を監視し、それらが(いつかでも)満たされているかどうかを確認することで回答できます。

2 番目の質問は、パラメータ設定の誤り、特定のアクションの使用方法の誤解、あるいは(望ましくは稀な)実際の AGM のバグによるアクションの問題である傾向があります。

printprint_debug(スクリプト名と行番号)、print_rich(色と VFX ハイライト)は、テキストログ上で監視を設定するための原始的な方法に過ぎません。これは、短期的なコード設計上の欠陥のデバッグには有用ですが、複雑で条件分岐の多い設計では有用性が低くなります。

「いいね!」 1