GodotでHTTPリクエストを送信する

今回はGodotでHTTPリクエストを送信するためのHTTPRequestノードについて説明します。
2023.11.30

Godotについて

GodotはMITライセンスで開発されているゲームエンジンです。

複数プラットフォームに対応したゲームエンジンで、PCだけでなくスマートフォンやWeb向けにもビルド可能です。

2014年から開発が開始されており、割と成熟したエンジンではありますが日々改善が施されています。

バージョン

今回使用しているのはGodot Engine v4.1.3です。

GodotとHTTP

ネットワークに接続するようなゲームを作りたい場合にHTTPリクエストを送りたいという場面も発生すると思います。

Godotでは以下の2つのノードが存在しています。

  • HTTPRequest: 高レイヤーのHTTPクライアント
  • HTTPClient: 低レイヤーのHTTPクライアント

個人的な意見としてはHTTPRequestの方を使用するのが便利だと思っています。より細かく制御したい場合はHTTPClientを使用することになるといった感じです。

HTTPRequestはスクリプトを書くうえでよりシンプルに書ける場合が多いです。

実際の使用例

今回はボタンを押したらHTTPリクエストが送信されるようなケースを想定しています。 ボタンが押されると_on_button_pressedが呼び出されます。

基本的な使い方はノードのインスタンスを作成し、それそシーンツリーに追加した後にリクエストを送信するといった形です。

HTTPSignalConnect.gd

extends Node2D

var http_request := HTTPRequest.new()

func _ready():
	add_child(http_request)
	http_request.request_completed.connect(self._http_request_completed)


func _on_button_pressed():
	var error = http_request.request("http://localhost:3000/res.json")
	
	if error != OK:
		push_error("HTTPリクエスト中にエラーが発生しました")
	
func _http_request_completed(result, response_code, headers, body):
	var json = JSON.new()
	json.parse(body.get_string_from_utf8())
	var response = json.get_data()
	$Label.text = response["message"]

注目すべき点は以下の部分です。

コールバック

    http_request.request_completed.connect(self._http_request_completed)

HTTPRequestはHTTPリクエストが完了するとrequest_completedシグナルが発行されます。 これによってコールバック関数(self._http_request_completed)が呼ばれるといった形です。

Pythonのurllibではそこで処理がブロックされてしまいますが、HTTPRequestではコールバックを登録して非同期的に処理が行われます。 JavaScriptのfetchでコールバックを渡したり、XMLHttpRequestにリスナーを登録するのと似たような感じです。

awaitを使った書き方

もう少し発展してawaitを使った方法を書いてみます。

HTTPSignalConnectAwait.gd

extends Node2D

var http_request := HTTPRequest.new()

func _ready():
	add_child(http_request)

func _on_button_pressed():
	var error = http_request.request("http://localhost:3000/res.json")

	if error != OK:
		push_error("HTTPリクエスト中にエラーが発生しました")

	var ret = await http_request.request_completed
	
	match ret:
		[var result, var response_code, var header, var body]:
			_http_request_completed(result, response_code, header, body)
		_:
			pass
	
func _http_request_completed(result, response_code, headers, body):
	var json = JSON.new()
	json.parse(body.get_string_from_utf8())
	var response = json.get_data()
	$Label.text = response["message"]

ほとんどコードは同じですが、_ready関数の中でシグナルの接続を行なっていない点が異なります。 こちらでは_on_button_pressed内でシグナルが発行されるのを待機しています。

HTTPレスポンスの結果を見てまた別のHTTPリクエストを送信したい場合などはこちらの方が綺麗に書けると思います。

最後に

GodotでもHTTPを使って通信が行えることを確認しました。 HTTPRequestノードを使用することでシグナルを使った非同期処理ができるので便利だと思います。