LoginSignup
1

Godot4.1.3でGodot State Charts 機能拡張プラグインを使う 1/2

Last updated at Posted at 2023-11-05

 Godot4用の機能拡張用プラグイン「Godot State Charts」をインストールすることで、状態遷移を簡単に実装することができるようになります。アプリを実装すると、変数とif文で管理するには複雑な状態遷移が必要になることがあるので、先行投資的な気持ちで使ってみました。

こちらにマニュアルがあります。

Godot State Chartについて

 State ChartのGodot実装です。最初からGodot用に設計し、ノードやシグナルをフル活用しているため、Godotユーザは理解しやすいと思います。また状態遷移は並列化したり、階層化にも対応しているため、複雑な状態をスマートに管理・制御することができそうです。また組み込みのデバッグビューを使用すると実行中に状態や、遷移条件を確認することができるため、便利です。
 ただし「状態遷移図」として表示できないため、あまり大規模な状態遷移をつくると全体を把握するのは難しそうですが、変数とif文やテーブルで管理するのに比べると、簡単で見やすくなります。

サンプルプログラムについて

 Godot State Chartsの使い方は動画で紹介されています。説明を補足しながら実装していきます。

Version

Godot4.1.3
Godot State Charts 0.7.1 ※

※まだ新しくてユーザも少ないため、バグや不足機能がある場合は教えてほしいとのことです

Godot State Chartsのインストールして有効化する

Godotプロジェクトを作成します。SampleStateChartsという名前にしました。
画面上部の「AssetLib」をクリックし、検索窓に「state charts」と入力すると、「Godot State Charts」が表示されるので、クリックします。
image.png
「ダウンロード」ボタンを押下します。
image.png
「インストール」ボタンを押下します。
image.png
「成功」のダイアログが表示されてインストールが完了します。
ファイルシステムを見ると、assetsフォルダの下に、godot_state_chartsがインストールされました。
その下の「godot_state_charts_examples」はサンプルプログラムがあり、より深く理解したい場合に活用できそうです。githubに簡単な説明があります。
image.png

インストール後はプラグインを有効にする必要があります。
「プロジェクト」メニューの「プロジェクト設定...」を実行します。
「プラグイン」タブをクリックすると、Godot State Chartsが表示されるので、ステータスを有効にします(チェックする)。
image.png

新規2Dシーンを作成して、見張り(Watchman)と敵(Enemy)を作成する

 StateChartのサンプルとして、見張り(Watchman)と敵(Enemy)を用意し、敵をマウスで動かして、見張りの監視範囲にいるかいないかをStateChartで管理します。
 簡単のため2Dで実装しています。

 見張り(Watchman)を作成します。
 新規2Dシーンを作成します。ルートノードはNode2Dです。
 子ノードにNode2Dを追加して、名前を「Watchman」にします。見張り役です。2Dエディターウインドウで中央に移動します。
Watchmanの子ノードにSprite2Dを追加します。インスペクターのTextureにicon.svgをドラッグします。
Watchmanの子ノードにArea2Dを追加し、さらに子ノードにCollisionShape2Dを追加します。インスペクタのShapeはCircleShape2Dにします。見張りの監視範囲なので下図のように広めに設定します。
image.png

 次に敵を作成します。
 Watchmanノードを複製して、名前を「Enemy」に変更します。
 移動したいので、Enemyを選択し、インスペクターのTransform/positionを(x,y)=(100px,100px)くらいにします。(Watchmanと重なっていなければ、どこでもよいです)
 Enemy/Sprite2Dを選択して、Scaleを0.6に変更して、アイコン表示を少し小さくします。
 Enemyの衝突範囲を小さくしたいのですが、Watchmanを複製したため、Watchman/CollisionShape2DとEnemy/CollisionShape2Dが同じCircleShape2Dを共有しています。個別に衝突範囲を設定したいので、Enemy/CollisionShape2Dを選択した状態で、インスペクターのShapeのCircleShape2Dをクリックして、ユニーク化します。
2023-11-04 (1).png
 その後に、衝突範囲を小さくします。
image.png

 敵はマウスで操作するため、Enemyにスクリプトをアタッチして下記のようにします。
 マウスの位置をそのまま、Enemyの位置に設定しています。

extends Node2D

func _process(delta):
   global_position = get_global_mouse_position()

コリジョン形状を表示して、見た目で衝突がわかるようにします。
2023-11-04 (3).png

実行します。
マウスの動きに合わせて敵(Enemy)が動くことを確認します
image.png

WatchmanノードにState Chartを追加する

 Watchmanノードの子ノードとして、StateChart(state_Chart.gd)を追加します。
image.png

 追加したStateChartを選択した状態で、画面上部の2D(もしくは3D)をクリックすると、エディターウィンドウの左側に、下図のようなStateChart用のノード追加ボタンが表示されます。名前を入力して、ボタンを押下すると簡単にStateChart用のノードを追加できます。またシーンで選択したノードに追加可能なノードのボタンのみ表示されるので、間違えにくく便利です。
(もしくは「子ノードを追加」を実行して、検索窓に「state」もしくは「transition」と入力することでStateChart用のノードを表示することができるので、選択して追加することもできます。)
2023-11-05.png

StateChartで使用するノード

 先ほど子ノードを追加から追加したStateChartノードに対してGDScriptからイベントやガード条件の変数を設定し、状態の変更などは子ノードからsignalの通知により知ることができます。
StateChartの配下には、ルートノードとしてひとつだけ、CompoundState(もしくはParallelState)を追加することができます。
 CompoundStateは通常2個以上の状態としてAtomicStateを持ち、AtomicStateがTransitionノードを持つという構造になります。

アイコン 名前 用途
image.png StateChartノード このノードに対してGDScriptからイベントやガード条件の変数を設定できます
image.png CompoundState 通常は2個以上の状態(AtomicState)を持ちます。初期状態を設定します
image.png AtomicState 1個の状態を表します。Transitionを子として持ちます。
image.png ParallelState 複数のCompoundStateを持つことが多いと思います。
image.png HistoryState 状態を記憶します
image.png Transition イベントを受けて状態遷移を定義します。Delayやガード条件も設定することができます。
image.png AnimationTreeState 本稿で未使用なので割愛
image.png AnimationPlayerState 本稿で未使用なので割愛

敵が接近した場合、監視中状態にする

 先ほど追加したStateChartを選択した状態で、名前「Root」でCompoundStateを追加します。
 Rootの子に、名前「Idle」と名前「Observing」のAtomicStateを追加します。
 敵が発見できていない状態がIdleで、発見するとObserving状態に遷移します。
 Idle状態からObserving状態に遷移したいので、遷移元のIdleを選択して、名前「To Observe」のTransitionを追加します。
image.png
 2つ警告マークが表示されているので、設定します。

 CompoundStateに初期状態を設定する必要があります。
 Rootを選択した状態で、インスペクターのCompoundStateのInitial StateにIdleを設定します。
image.png

 Transitionに状態遷移の遷移先とイベント名を設定します。
 「To Observing」Transitionノードを選択した状態でインスペクターのTransionのToに遷移先としたい「Observing」状態を設定します。Eventは「enemy_entered」と手入力します。
 この設定により、GDScriptからStateChartノードのsend_eventメソッドで"enemy_entered"イベントを送ると、Toで設定した遷移先「Observing」状態に遷移するようになります。
2023-11-05 (1).png

 次に、WatchmanのArea2DでEnemyを検知した場合に、状態遷移するようにします。
 Watchmanにスクリプトをアタッチします。
 Watchman/Area2Dを選択し、ノード/シグナルから「area_entered」シグナルをダブルクリックして、Watchmanのスクリプトに接続します。
 Watchmanのスクリプトを下記のようにして、Area2Dでareaを検知した時はStateChartに"enemy_entered"イベントを送信するようにします。

extends Node2D

func _on_area_2d_area_entered(area):
	$StateChart.send_event("enemy_entered")

StateChartデバッガを表示して、実行中に状態を確認できるようにする

 ルートノードの「Node2D」を選択して、「Instantiate Child Scnene」を実行して、「addons/godot_state_charts/utilities/state_chart_debugger.tscn」を追加します。
image.png

 2Dのエディターウインドウの左上に小さく表示されるので、大きくして右の方に配置します。
image.png
 またStateChartDebuggerのインスペクターの「Initial Node to Watch」にデバッグ対象のStateChartを選択します。
image.png

実行して状態遷移を確認する

 実行します。
 初期状態はIdleで表示されています。
2023-11-05 (5).png
 マウスで敵を動かして、Watchmanの衝突領域に触れると、状態が「Observing」に遷移します。
2023-11-05 (6).png

 状態遷移が動くのを確認できました。
 まだ続きがありますが、長くなったのでここまでにします。

github

 ここまで作ったものをgithubに登録しましたが、State Chartは別途ダウンロードが必要です。

実行する前に必要な手順

  1. Godotにインポート
  2. AssetLibからState Chartをダウンロード
  3. プロジェクト設定のプラグインタブでState Chartを有効化する

 以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1