RPC 機能¶
Sora Unity SDK の RPC 機能について説明します。
注意
この機能は実験的機能のため、正式版では仕様が変更される可能性があります
RPC 機能について¶
RPC 機能は DataChannel 経由で Sora の一部 HTTP API を利用するための機能です。 JSON-RPC 2.0 プロトコルの仕様に準拠しています。
この機能は Sora 2025.2 以降で、かつ DataChannel 経由のシグナリングが有効な場合に利用可能です。 Sora の RPC 機能の詳細は Sora ドキュメントの RPC 機能 をご確認ください。
利用時の注意事項¶
label が
rpcのメッセージはSora.OnMessageには届きませんRPC レスポンス受信とタイムアウト判定は
Sora.DispatchEvents()の呼び出しで処理されますDispatchEvents()を定期的に呼び出さない場合、コールバックは呼ばれず、タイムアウトも返りません
切断時、およびアプリ終了に伴う
Dispose()実行時、未完了の RPC リクエストは破棄されますparamsJsonは JSON 文字列をそのまま埋め込むため、JSON を渡してください
Sora Unity SDK の実装内容¶
Sora Unity SDK では RPC の送信とレスポンス受信を以下の API で提供しています。
void RequestRpcNotification(string method, string paramsJson): JSON-RPC 2.0 Notification を送信void RequestRpc(string method, string paramsJson, Action<RpcResult> onResult, long timeoutMillis): JSON-RPC 2.0 Request を送信(タイムアウトをミリ秒で指定)
RequestRpcNotification のパラメータ¶
method: 呼び出すメソッド名 (例:"2025.2.0/RequestSimulcastRid")paramsJson: メソッドのパラメータを表す JSON 文字列。オブジェクト形式 (例:{"key":"value"}) または配列形式 (例:[1,2,3]) で指定します。パラメータがない場合は"{}"を指定してください
注釈
JSON-RPC 2.0 Notification として送信されます。この場合 Sora はレスポンスを返しません。
RequestRpc のパラメータ¶
method: 呼び出すメソッド名 (例:"2025.2.0/RequestSimulcastRid")paramsJson: メソッドのパラメータを表す JSON 文字列。オブジェクト形式 (例:{"key":"value"}) または配列形式 (例:[1,2,3]) で指定します。パラメータがない場合は"{}"を指定してくださいonResult:Sora.RpcResult型のレスポンス用のコールバックtimeoutMillis: Sora レスポンスのタイムアウト時間(ミリ秒)。0より大きな値を指定してくださいSora.DefaultRpcTimeoutMillisで指定すると 5,000 ms となります
注釈
SDK は内部でリクエスト ID を自動採番し、レスポンスと紐付けます。アプリケーション側で ID を指定することはできません。
RpcResult のメンバー¶
ResultKind: RPC リクエスト結果です。Response/Timeoutのいずれかが入りますMethod: RPC リクエストしたメソッドです。リクエスト時に指定したメソッドと同じものが入りますParamsJson: RPC リクエストパラメータの JSON 文字列です。リクエスト時に指定した JSON 文字列と同じものが入りますResponseJson: RPC レスポンスの JSON 文字列です。データ内容のパースは SDK の利用者側の責務となります
重要
ResultKind.Response は Sora からの RPC レスポンスを受信することができたことのみを表し、リクエスト内容の成功 / 失敗を表しません。
ResponseJson の内容(result / error)を利用者側で判定してください
利用方法¶
シグナリング設定¶
Sora Unity SDK Examples の SoraSample.cs では、Inspector で dataChannel signaling を設定し、
Sora.Config に反映しています。
以下のように DataChannel 経由のシグナリングを有効にする設定を行います。
var config = new Sora.Config()
{
EnableDataChannelSignaling = true,
DataChannelSignaling = true,
};
RPC リクエストの送信とレスポンス受信¶
ここでは UI のボタンから RPC リクエストを送信し、レスポンスを受信する例を示します。
レスポンスデータはコールバックで受け取るため、レスポンスデータを処理するコールバックハンドラを Sora.RpcResult 型で用意します。
また受信したレスポンスデータは JSON 形式の文字列です。パース処理は独自に実装する必要があります。
重要
Sora.RequestRpc に渡される onResult コールバックは DispatchEvents() で処理されるため、 Update() で定期的に DispatchEvents() が呼ばれている必要があります。
// SoraSample.cs からの抜粋した RPC 機能を使用するための設定パラメータと送信/受信メソッドの例です。
// [Header]`` 属性が付与されたフィールドで、各 RPC メソッドのパラメータを Inspector から設定できます。
// 送信する RPC メッセージの種類
public enum RpcMessageType
{
None,
RequestSimulcastRid,
RequestSpotlightRid,
ResetSpotlightRid,
PutSignalingNotifyMetadata,
PutSignalingNotifyMetadataItem,
}
[Header("RPC メッセージの設定")]
// Inspector で送信したい RPC メッセージの種類を選択します
public RpcMessageType rpcMessageType = RpcMessageType.None;
// RPC リクエストの timeoutMillis(ミリ秒)。空欄の場合は SDK のデフォルト値を利用します
public string rpcTimeoutMillis = "";
[Header("RequestSimulcastRid の設定")]
public string sendRequestSimulcastRid = "r0";
public string sendRequestSimulcastRidSenderConnectionId = "";
[Header("RequestSpotlightRid の設定")]
public string sendRequestSpotlightFocusRid = "r1";
public string sendRequestSpotlightUnfocusRid = "none";
public string sendRequestSpotlightRidConnectionId = "";
[Header("ResetSpotlightRid の設定")]
public string sendResetSpotlightRidConnectionId = "";
[Header("PutSignalingNotifyMetadata の設定")]
public string sendPutSignalingNotifyMetadataJson = "{\"key\":\"value\"}";
public bool sendPutSignalingNotifyMetadataPush = false;
[Header("PutSignalingNotifyMetadataItem の設定")]
public string sendPutSignalingNotifyMetadataItemKey = "status";
public string sendPutSignalingNotifyMetadataItemValue = "\"active\"";
public bool sendPutSignalingNotifyMetadataItemPush = false;
// ボタンを押したときに呼び出される RPC 送信メソッド例
// RpcMessageType enum で送信する RPC メッセージの種類を選択します。
public void OnClickSendRpc()
{
if (sora == null)
{
return;
}
// Inspector で選択された RPC メッセージの種類に応じて処理を分岐する
switch (rpcMessageType)
{
case RpcMessageType.None:
Debug.Log("RPC メッセージの種類が選択されていません");
break;
case RpcMessageType.RequestSimulcastRid:
SendRequestSimulcastRid();
break;
case RpcMessageType.RequestSpotlightRid:
SendRequestSpotlightRid();
break;
case RpcMessageType.ResetSpotlightRid:
SendResetSpotlightRid();
break;
case RpcMessageType.PutSignalingNotifyMetadata:
SendPutSignalingNotifyMetadata();
break;
case RpcMessageType.PutSignalingNotifyMetadataItem:
SendPutSignalingNotifyMetadataItem();
break;
}
}
// レスポンスをコールバックで受け取るハンドラです
// sora.RequestRpc の引数に指定します
void HandleRpcResult(Sora.RpcResult result) {
switch (result.ResultKind) {
// レスポンスを受信できた場合です
// レスポンスの内容が成功かエラーか判定するにはさらにレスポンスデータをパースする必要があります
case Sora.RpcResultKind.Response:
{
var responseJson = result.ResponseJson;
Debug.LogFormat("RPC response: method={0}, response={1}", result.Method, responseJson);
// JSON-RPC 2.0 の result / error 判定例
// 実際には JSON パーサーを使用してください
if (responseJson != null && responseJson.Contains("\"result\""))
{
Debug.Log("RPC result が返りました");
}
else if (responseJson != null && responseJson.Contains("\"error\""))
{
Debug.LogError("RPC error が返りました");
}
break;
}
// リクエストがタイムアウトになった場合です
case Sora.RpcResultKind.Timeout:
Debug.LogErrorFormat("RPC timeout: method={0}", result.Method);
break;
}
}
// Sora.RequestRpc メソッドを利用して RPC リクエストします
void RequestRpcInternal(string method, string paramsJson)
{
if (sora == null)
{
return;
}
// タイムアウト時間無指定であれば Sora.DefaultRpcTimeoutMillis を指定します
if (string.IsNullOrWhiteSpace(rpcTimeoutMillis))
{
sora.RequestRpc(method, paramsJson, HandleRpcResult, Sora.DefaultRpcTimeoutMillis);
return;
}
// タイムアウト時間は long 型のためパースします
var timeoutMillisText = rpcTimeoutMillis.Trim();
if (!long.TryParse(timeoutMillisText, out var timeoutMillis))
{
Debug.LogErrorFormat("RPC timeoutMillis の形式が不正です: timeoutMillis={0}", rpcTimeoutMillis);
return;
}
if (timeoutMillis <= 0)
{
Debug.LogErrorFormat("RPC timeoutMillis は 1 以上を指定してください: timeoutMillis={0}", timeoutMillis);
return;
}
sora.RequestRpc(method, paramsJson, HandleRpcResult, timeoutMillis);
}
// 各 RPC メソッド ( SendRequestSimulcastRid、SendRequestSpotlightRid など) は、
// Inspector で選択されたメッセージタイプに応じて OnClickSendRpc() から呼び出されます。
// 実際の RPC リクエストは sora.RequestRpc() メソッドを使用して送信されます。
void SendRequestSimulcastRid()
{
Debug.LogFormat("SendRequestSimulcastRid: rid={0}, sender_connection_id={1}", sendRequestSimulcastRid, sendRequestSimulcastRidSenderConnectionId);
string paramsJson;
if (string.IsNullOrEmpty(sendRequestSimulcastRidSenderConnectionId))
{
paramsJson = $"{{\"rid\":\"{sendRequestSimulcastRid}\"}}";
}
else
{
paramsJson = $"{{\"sender_connection_id\":\"{sendRequestSimulcastRidSenderConnectionId}\",\"rid\":\"{sendRequestSimulcastRid}\"}}";
}
RequestRpcInternal("2025.2.0/RequestSimulcastRid", paramsJson);
}
void SendRequestSpotlightRid()
{
Debug.LogFormat("SendRequestSpotlightRid: focus={0}, unfocus={1}, send_connection_id={2}", sendRequestSpotlightFocusRid, sendRequestSpotlightUnfocusRid, sendRequestSpotlightRidConnectionId);
string paramsJson;
if (string.IsNullOrEmpty(sendRequestSpotlightRidConnectionId))
{
paramsJson = $"{{\"spotlight_focus_rid\":\"{sendRequestSpotlightFocusRid}\",\"spotlight_unfocus_rid\":\"{sendRequestSpotlightUnfocusRid}\"}}";
}
else
{
paramsJson = $"{{\"send_connection_id\":\"{sendRequestSpotlightRidConnectionId}\",\"spotlight_focus_rid\":\"{sendRequestSpotlightFocusRid}\",\"spotlight_unfocus_rid\":\"{sendRequestSpotlightUnfocusRid}\"}}";
}
RequestRpcInternal("2025.2.0/RequestSpotlightRid", paramsJson);
}
void SendResetSpotlightRid()
{
Debug.LogFormat("SendResetSpotlightRid: send_connection_id={0}", sendResetSpotlightRidConnectionId);
string paramsJson;
if (string.IsNullOrEmpty(sendResetSpotlightRidConnectionId))
{
paramsJson = "{}";
}
else
{
paramsJson = $"{{\"send_connection_id\":\"{sendResetSpotlightRidConnectionId}\"}}";
}
RequestRpcInternal("2025.2.0/ResetSpotlightRid", paramsJson);
}
void SendPutSignalingNotifyMetadata()
{
Debug.LogFormat("SendPutSignalingNotifyMetadata: {0}", sendPutSignalingNotifyMetadataJson);
string paramsJson = sendPutSignalingNotifyMetadataPush
? $"{{\"push\":true,\"metadata\":{sendPutSignalingNotifyMetadataJson}}}"
: $"{{\"metadata\":{sendPutSignalingNotifyMetadataJson}}}";
RequestRpcInternal("2025.2.0/PutSignalingNotifyMetadata", paramsJson);
}
void SendPutSignalingNotifyMetadataItem()
{
Debug.LogFormat("SendPutSignalingNotifyMetadataItem: key={0}, value={1}", sendPutSignalingNotifyMetadataItemKey, sendPutSignalingNotifyMetadataItemValue);
string paramsJson = sendPutSignalingNotifyMetadataItemPush
? $"{{\"push\":true,\"key\":\"{sendPutSignalingNotifyMetadataItemKey}\",\"value\":{sendPutSignalingNotifyMetadataItemValue}}}"
: $"{{\"key\":\"{sendPutSignalingNotifyMetadataItemKey}\",\"value\":{sendPutSignalingNotifyMetadataItemValue}}}";
RequestRpcInternal("2025.2.0/PutSignalingNotifyMetadataItem", paramsJson);
}
// コールバック発火のため DispatchEvents の定期的な呼び出しが必要です
void Update()
{
if (sora != null)
{
sora.DispatchEvents();
}
}