GDScript で書かれた NAKAMA サーバー用の Godot クライアント。
nakama は、最新のゲームやアプリを強化するために設計されたオープンソース サーバーです。ユーザー アカウント、チャット、ソーシャル、マッチメーカー、リアルタイム マルチプレイヤーなどの機能が含まれます。
このクライアントは、サーバーの完全な API とソケット オプションを実装します。 Godot Engine 4.0+
をサポートするために GDScript で書かれています。
完全なドキュメントはオンラインです - https://heroiclabs.com/docs
現在、Godot 用の NAKAMA クライアントの Godot 4 バージョンを表示しています。
Godot 3 を使用している場合は、GitHub の「godot-3」ブランチを使用する必要があります。
クライアントに接続する前に、サーバーとデータベースをセットアップする必要があります。最も簡単な方法は Docker を使用することですが、他のオプションについてはサーバーのドキュメントを参照してください。
サーバーをインストールして実行します。以下の指示に従ってください。
リリース ページからクライアントをダウンロードし、プロジェクトにインポートします。アセット リポジトリからダウンロードすることもできます。
Nakama.gd
シングルトン ( addons/com.heroiclabs.nakama/
内) を Godot の自動ロードとして追加します。
接続資格情報を使用して、シングルトンを使用してクライアント オブジェクトを構築します。
extends Node
func _ready ():
var scheme = "http"
var host = "127.0.0.1"
var port = 7350
var server_key = "defaultkey"
var client := Nakama . create_client ( server_key , host , port , scheme )
クライアント オブジェクトには、サーバーでさまざまな機能を実行したり、サーバーとのリアルタイム ソケット接続を開くためのメソッドが多数あります。
サーバーで認証するにはさまざまな方法があります。これらの資格情報を持つユーザーがまだ存在していない場合、認証によってユーザーを作成できます。 Google Play ゲーム、Facebook、Game Center などのソーシャル プロファイルを使用して認証することも簡単です。
var email = "[email protected]"
var password = "batsignal"
# Use 'await' to wait for the request to complete.
var session : NakamaSession = await client . authenticate_email_async ( email , password )
print ( session )
認証されると、サーバーは有用なプロパティを含む認証トークン (JWT) で応答し、 NakamaSession
オブジェクトに逆シリアル化されます。
print ( session . token ) # raw JWT token
print ( session . user_id )
print ( session . username )
print ( "Session has expired: %s " % session . expired )
print ( "Session expires at: %s " % session . expire_time )
セッションから認証トークンを保存し、起動時に有効期限が切れているかどうかを確認することをお勧めします。トークンの有効期限が切れた場合は、再認証する必要があります。トークンの有効期限はサーバーの設定として変更できます。
var authtoken = "restored from somewhere"
var session2 = NakamaClient . restore_session ( authtoken )
if session2 . expired :
print ( "Session has expired. Must reauthenticate!" )
注: セッションの存続期間の長さは、サーバー上で--session.token_expiry_sec
コマンド フラグ引数を使用して変更できます。
クライアントには、ゲーム サーバーのさまざまな機能用の組み込み API が多数含まれています。これらには、非同期メソッドを使用してアクセスできます。サーバー上の RPC 関数でカスタム ロジックを呼び出すこともできます。これらはソケット オブジェクトを使用して実行することもできます。
すべてのリクエストは、クライアントを許可するセッション オブジェクトとともに送信されます。
var account = await client . get_account_async ( session )
print ( account . user . id )
print ( account . user . username )
print ( account . wallet )
Godot Engine は例外をサポートしていないため、クライアントまたはソケット経由で非同期リクエストを行うたびに、 is_exception()
メソッド経由でエラーが発生したかどうかを確認できます。
var an_invalid_session = NakamaSession . new () # An empty session, which will cause and error when we use it.
var account2 = await client . get_account_async ( an_invalid_session )
print ( account2 ) # This will print the exception
if account2 . is_exception ():
print ( "We got an exception" )
クライアントはサーバーに対して 1 つ以上のソケットを作成できます。各ソケットには、サーバーから受信した応答用に登録された独自のイベント リスナーを持つことができます。
var socket = Nakama . create_socket_from ( client )
socket . connected . connect ( self . _on_socket_connected )
socket . closed . connect ( self . _on_socket_closed )
socket . received_error . connect ( self . _on_socket_error )
await socket . connect_async ( session )
print ( "Done" )
func _on_socket_connected ():
print ( "Socket connected." )
func _on_socket_closed ():
print ( "Socket closed." )
func _on_socket_error ( err ):
printerr ( "Socket error %s " % err )
Godot は高レベルのマルチプレイヤー API を提供しており、開発者は RPC を作成して、マルチプレイヤー マッチの他のピアで実行される関数を呼び出すことができます。
例えば:
func _process ( delta ):
if not is_multiplayer_authority ():
return
var input_vector = get_input_vector ()
# Move the player locally.
velocity = input_vector * SPEED
move_and_slide ()
# Then update the player's position on all other connected clients.
update_remote_position . rpc ( position )
@rpc ( any_peer )
func update_remote_position ( new_position ):
position = new_position
Godot は、ENet、WebSocket、WebRTC など、RPC を送信するための多数の組み込みバックエンドを提供します。
ただし、Nakama クライアントをバックエンドとして使用することもできます。これにより、Godot の使い慣れたハイレベル マルチプレイヤー API を引き続き使用できますが、RPC はリアルタイムのナカマ マッチを通じて透過的に送信されます。
これを行うには、 NakamaMultiplayerBridge
クラスを使用する必要があります。
var multiplayer_bridge
func _ready ():
# [...]
# You must have a working 'socket', created as described above.
multiplayer_bridge = NakamaMultiplayerBridge . new ( socket )
multiplayer_bridge . match_join_error . connect ( self . _on_match_join_error )
multiplayer_bridge . match_joined . connect ( self . _on_match_joined )
get_tree (). get_multiplayer (). set_multiplayer_peer ( multiplayer_bridge . multiplayer_peer )
func _on_match_join_error ( error ):
print ( "Unable to join match: " , error . message )
func _on_match_join () -> void :
print ( "Joined match with id: " , multiplayer_bridge . match_id )
MultiplayerAPI
上の通常のシグナルのいずれかに接続することもできます。次に例を示します。
get_tree (). get_multiplayer (). peer_connected . connect ( self . _on_peer_connected )
get_tree (). get_multiplayer (). peer_disconnected . connect ( self . _on_peer_disconnected )
func _on_peer_connected ( peer_id ):
print ( "Peer joined match: " , peer_id )
func _on_peer_disconnected ( peer_id ):
print ( "Peer left match: " , peer_id )
次に、次のいずれかの方法を使用して試合に参加する必要があります。
クライアントをホストとして、新しいプライベート マッチを作成します。
multiplayer_bridge . create_match ()
プライベートマッチに参加してください。
multiplayer_bridge . join_match ( match_id )
指定された名前でプライベート マッチを作成または参加します。
multiplayer_bridge . join_named_match ( match_name )
マッチメーカーを使用して公開マッチを見つけて参加します。
var ticket = await socket . add_matchmaker_async ()
if ticket . is_exception ():
print ( "Error joining matchmaking pool: " , ticket . get_exception (). message )
return
multiplayer_bridge . start_matchmaking ( ticket )
「match_joined」シグナルが発行された後、 rpc()
関数を使用して通常どおり RPC の送信を開始し、 get_tree().get_multiplayer().get_unique_id()
などの高レベル マルチプレイヤー API に関連付けられた他の関数の呼び出しを開始できます。 get_tree().get_multiplayer().get_unique_id()
、 node.set_network_authority(peer_id)
、およびnode.is_network_authority()
。
C# サポートを備えた Godot の .NET バージョンを使用している場合は、NuGet 経由でインストールできるnakama .NET クライアントを使用できます。
dotnet add package NakamaClient
このアドオンには、Godot とのより深い統合を提供するために、.NET クライアントで使用するためのいくつかの C# クラスが含まれています。
GodotLogger
: Godot コンソールに出力するロガー。GodotHttpAdapter
: Godot の HTTPRequest ノードを使用する HTTP アダプター。GodotWebSocketAdapter
: Godot の WebSocketClient を使用するソケット アダプター。これらの使用方法の例を次に示します。
var http_adapter = new GodotHttpAdapter ( ) ;
// It's a Node, so it needs to be added to the scene tree.
// Consider putting this in an autoload singleton so it won't go away unexpectedly.
AddChild ( http_adapter ) ;
const string scheme = "http" ;
const string host = "127.0.0.1" ;
const int port = 7350 ;
const string serverKey = "defaultkey" ;
// Pass in the 'http_adapter' as the last argument.
var client = new Client ( scheme , host , port , serverKey , http_adapter ) ;
// To log DEBUG messages to the Godot console.
client . Logger = new GodotLogger ( "Nakama" , GodotLogger . LogLevel . DEBUG ) ;
ISession session ;
try {
session = await client . AuthenticateDeviceAsync ( OS . GetUniqueId ( ) , "TestUser" , true ) ;
}
catch ( ApiResponseException e ) {
GD . PrintErr ( e . ToString ( ) ) ;
return ;
}
var websocket_adapter = new GodotWebSocketAdapter ( ) ;
// Like the HTTP adapter, it's a Node, so it needs to be added to the scene tree.
// Consider putting this in an autoload singleton so it won't go away unexpectedly.
AddChild ( websocket_adapter ) ;
// Pass in the 'websocket_adapter' as the last argument.
var socket = Socket . From ( client , websocket_adapter ) ;
注:すぐに使えるnakama .NET クライアントは、ゲームのデスクトップ ビルドで正常に動作します。ただし、 GodotHttpAdapter
クラスとGodotWebSocketAdapter
クラスを使用しない限り、HTML5 ビルドでは機能しません。
Satori は、実用的な分析、A/B テスト、リモート構成を強化するゲーム用の Liveops サーバーです。 Satori Godot クライアントを使用して、Godot ゲーム内からSatori と通信します。
Satori は Godot 4 とのみ互換性があります。
完全なドキュメントはオンラインです - https://heroiclabs.com/docs/satori/client-libraries/godot/index.html
Satori.gd
シングルトン ( addons/com.heroiclabs.nakama/
内) を Godot の自動ロードとして追加します。
Satori 顧客として与えられた API キーを受け入れるクライアント オブジェクトを作成します。
extends Node
func ready ():
var scheme = "http"
var host = "127.0.0.1"
var port : Int = 7450
var apiKey = "apiKey"
var client := Satori . create_client ( apiKey , host , port , scheme )
次に、サーバーで認証してセッションを取得します。
// Authenticate with the Satori server .
var session = await _client . authenticate_async ( "your-id" )
if session . is_exception ():
print ( "Error authenticating: " + session . get_exception (). _message )
else :
print ( "Authenticated successfully." )
クライアントを使用すると、ユーザーが属する実験や機能フラグを取得できます。
var experiments = await _client . get_experiments_async ( session , [ "experiment1" , "Experiment2" ])
var flag = await _client . get_flag_async ( session , "FlagName" )
任意のイベントをサーバーに送信することもできます。
var _event = Event . new ( "gameFinished" , Time . get_unix_time_from_system ())
await _client . event_async ( session , _event )
開発ロードマップは GitHub Issue として管理されており、プル リクエストを歓迎します。コードの改善に興味がある場合は、問題を開いて変更について議論するか、コミュニティ フォーラムに参加して議論してください。
テストを実行するには、サーバーとデータベースを実行する必要があります。ほとんどのテストは、サーバーに対して実行される統合テストとして作成されます。テスト ワークフローで使用する簡単なアプローチは、ドキュメントで説明されている Docker compose ファイルを使用することです。
さらに、 test_suite
フォルダー内のaddons
フォルダーをコピー (またはシンボリックリンク) する必要があります。これで、Godot エディタからtest_suite
プロジェクトを実行できるようになりました。
ヘッドレス マシン (GPU なし) でテストを実行するには、Godot Headless のコピーをダウンロードし、コマンド ラインから実行します。
この手順を自動化するには、ヘッドレス バイナリをtest_suite/bin/godot.elf
に移動し、 test_suite/run_tests.sh
シェル スクリプトを介してテストを実行します (終了コードはテストの失敗/成功を報告します)。
cd nakama
docker-compose -f ./docker-compose-postgres.yml up
cd ..
cd nakama-godot
sh test_suite/run_tests.sh
新しいリリースを配布できるようにするには、アドオン フォルダーを再帰的に圧縮するだけです (場合によってはCHANGELOG
、 LICENSE
、およびREADME.md
も追加します)。
UNIX システムでは、次のコマンドを実行できます ( $VERSION
目的のバージョン番号に置き換えます)。最初にCHANGELOG
ファイルを忘れずに更新してください。
zip -r nakama- $VERSION .zip addons/ LICENSE CHANGELOG.md README.md
このプロジェクトは、Apache-2 ライセンスに基づいてライセンスされています。