ナビゲーションにスキップ

Unity SDK

ElevenAgents SDK:カスタマイズ可能なインタラクティブ音声エージェントをUnityゲームに導入します。

ElevenAgentsの仕組みについては、ElevenAgentsの概要を参照してください。

ElevenAgents Unity SDKは、UnityシーンをElevenLabsエージェントに接続します。プレイヤーのマイクをキャプチャし、エージェントの音声をAudioSource経由でストリーミングし、Editor、デスクトップスタンドアロンプレイヤー、WebGLビルドで同じように動作する単一のConversation APIを通じてセッションを公開します。

要件

  • Unity 6.3 LTS(6000.3.0f1)以降。SDKはUnity 6.3で導入されたスクリプタブルオーディオAPIを使用します。
  • Api Compatibility Levelを .NET Standard 2.1に設定。これはUnity 2023.1以降のデフォルトです。
  • ElevenLabsアカウントとエージェント。ダッシュボードで作成するか、クイックスタートに従ってください。

プラットフォーム対応

ターゲットトランスポートステータス
Editor(Play Mode)、デスクトップスタンドアロン(macOS、Windows、Linux)ネイティブWebSocket対応済み
WebGLJSブリッジ経由の@elevenlabs/client対応済み(WebSocketおよびWebRTC)
iOS、Android、XRネイティブWebSocket未テスト

SDKは、アクティブなビルドターゲットに応じてトランスポートを自動選択します。WebRTCはWebGLでのみ利用できます。その他すべてのターゲットでは、ConnectionType.WebRTCはNotSupportedExceptionをスローします。

SDKはマイク権限をリクエストしません。iOSおよびAndroidでは、セッションを開始する前に自分でリクエストしてください。

インストール

UnityでWindow > Package Managerを開き、+ > Install package from git URLを選択して、リポジトリURLを貼り付けます。

https://github.com/elevenlabs/unity.git

Package Managerは、依存関係のInput SystemおよびNewtonsoft Jsonとともに、パッケージをElevenAgents(io.elevenlabs.agents)としてインストールします。

パッケージには2つのサンプルが含まれています。Package Manager > ElevenAgents > Samplesからインポートしてください。QuickStartは、ライブ文字起こしを表示する単一のMonoBehaviourです。GettingStartedは、空間オーディオと動的変数を備えた、近づいて話しかけるためのシーンです。手順ごとのガイドは、Getting started walkthroughを参照してください。

クイックスタート

このセクションでは、空のシーンに音声エージェントを追加します。Play Modeに入るとエージェントが話し始め、Play Modeを終了するとセッションも終了します。

1

パブリックエージェントを作成する

ElevenLabsダッシュボードでエージェントを作成します。エージェントのSecurity設定でAuthenticationをオフにすると、ゲームはエージェントIDだけで接続できます。エージェントIDをコピーしてください。

認証が必要なエージェントについては、パブリックエージェントとプライベートエージェントを参照してください。

2

SDKをインストールする

インストールで説明したとおりに、git URLからパッケージをインストールします。

3

会話スクリプトを追加する

Assets/Scripts/AgentConversation.csを作成します。

AgentConversation.cs
using System;
using ElevenLabs.Agents;
using ElevenLabs.Protocol;
using UnityEngine;
public sealed class AgentConversation : MonoBehaviour
{
[SerializeField]
private string agentId = "agent_7101k5zvyjhmfg983brhmhkd98n6";
private Conversation conversation;
private async void Start()
{
try
{
conversation = await Conversation.StartSessionAsync(
new ConversationOptions { AgentId = agentId }
);
}
catch (Exception ex)
{
Debug.LogError($"Failed to start session: {ex.Message}");
return;
}
Debug.Log($"Connected: {conversation.ConversationId}");
conversation.UserTranscriptReceived += OnUserTranscript;
conversation.AgentResponded += OnAgentResponse;
conversation.ErrorOccurred += message => Debug.LogError(message);
conversation.Disconnected += details => Debug.Log($"Disconnected: {details.Reason}");
}
private void OnUserTranscript(UserTranscriptArgs args) =>
Debug.Log($"User: {args.UserTranscript}");
private void OnAgentResponse(AgentResponseArgs args) =>
Debug.Log($"Agent: {args.AgentResponse}");
private void OnDestroy()
{
_ = conversation?.EndSession();
}
}

Conversation.StartSessionAsyncは、接続が開き、オーディオデバイスの準備が整うと返ります。EndSessionはべき等であるため、セッションがすでに終了していてもOnDestroyから安全に呼び出せます。

4

シーンを実行する

空のGameObjectを作成し、AgentConversationコンポーネントを追加して、Agent IdフィールドにエージェントIDを貼り付けます。Play Modeに入り、OSから求められた場合はマイクアクセスを許可してください。エージェントが最初のメッセージを話し、文字起こしがConsoleに表示されます。

パブリックエージェントとプライベートエージェント

エージェントIDを直接渡します。IDを知っている人は誰でも、エージェントとの会話を開始できます。

var conversation = await Conversation.StartSessionAsync(
new ConversationOptions { AgentId = "agent_7101k5zvyjhmfg983brhmhkd98n6" }
);

AgentId、SignedUrl、ConversationTokenのいずれか1つだけを設定してください。独自システム内のプレイヤーと会話を関連付けるには、UserIdを設定します。

空間オーディオ

デフォルトでは、SDKが作成する非表示のAudioSourceを通じてエージェントの音声を再生します。シーン内に音声を配置するには、独自のAudioSourceをOutputAudioSourceとして渡します。

[SerializeField]
private AudioSource voiceSource; // Spatial Blend = 1 for 3D audio
var conversation = await Conversation.StartSessionAsync(
new ConversationOptions
{
AgentId = "agent_7101k5zvyjhmfg983brhmhkd98n6",
OutputAudioSource = voiceSource,
}
);

SDKは、ソースの空間ブレンド、ロールオフ、ミキサールーティング、位置を維持します。セッション終了時には、ソースのクリップ、ループ、音量設定を復元します。

口のアニメーションなど、エージェントの音声で視覚効果を動かすには、毎フレームconversation.GetOutputVolume()を読み取ります。すべてのプラットフォームで、0から1までの値を返します。

パーソナライズ

動的変数を使用すると、エージェントのプロンプトと最初のメッセージ内のプレースホルダーを入力できます。また、オーバーライドを使用すると、1つのセッションについてエージェント設定の一部を置き換えられます。

using System.Collections.Generic;
using ElevenLabs.Protocol;
var options = new ConversationOptions
{
AgentId = "agent_7101k5zvyjhmfg983brhmhkd98n6",
DynamicVariables = new Dictionary<string, object>
{
["player_name"] = "Ada",
["quest_stage"] = 3,
},
Overrides = new ConversationConfigOverride
{
Agent = new ConversationConfigOverrideAgent
{
FirstMessage = "Welcome back, {{player_name}}.",
},
Tts = new ConversationConfigOverrideTts { VoiceId = "JBFqnCBsd6RMkjVDRZzb" },
},
};

動的変数の値には、文字列、数値、またはブール値を使用する必要があります。サーバーが受け入れる前に、各オーバーライドをエージェントのSecurity設定で有効にする必要があります。

クライアントツール

クライアントツールを使うと、エージェントはゲーム内でアクションをトリガーできます。エージェント設定でツールを定義してから、同じ名前のハンドラーを登録します。

using Newtonsoft.Json;
public sealed class OpenDoorParams
{
[JsonProperty("door_id")]
public string DoorId { get; set; }
}
conversation.RegisterTool<OpenDoorParams, string>("open_door", parameters =>
{
DoorRegistry.Open(parameters.DoorId);
return $"Door {parameters.DoorId} is open.";
});

SDKはNewtonsoft Jsonを使用してツールパラメータをTParamsにデシリアライズするため、パラメータ名がプロパティ名と異なる場合は[JsonProperty]を使用してください。戻り値はツール結果としてシリアライズされます。非同期ハンドラーにはAwaitable<TResult>を返します。特定の失敗をエージェントに報告するには、errorTypeを指定してClientToolExceptionをスローします。その他の例外は一般的なエラーとして報告されます。

登録済みハンドラーのないツール呼び出しでは、ErrorOccurredが発生します。UnhandledClientToolCallを購読している場合は、代わりにそちらが発生します。

イベント

StartSessionAsyncが返すConversationのイベントを購読します。SDKはUnityのメインスレッドでこれらを発生させます。

イベントペイロード説明
DisconnectedDisconnectionDetailsセッションが終了しました。ReasonはUser、Agent、またはErrorです。
ErrorOccurredstringセッション開始後にエラーが発生しました。
StatusChangedStatus接続ステータスが変更されました。
ModeChangedModeエージェントがSpeakingとListeningを切り替えました。
UserTranscriptReceivedUserTranscriptArgsプレイヤーの発話の確定済み文字起こし。
AgentRespondedAgentResponseArgsエージェント応答のテキスト。
InterruptedInterruptionArgsプレイヤーがエージェントを中断しました。
AgentToolRequestedAgentToolRequestArgsエージェントがツール呼び出しを開始しました。完了時にAgentToolRespondedが発生します。
UnhandledClientToolCallClientToolCallArgsエージェントが、登録済みハンドラーのないクライアントツールを呼び出しました。
CanSendFeedbackChangedbool最新のエージェント応答に対するフィードバックが利用可能または利用不可になりました。

ConnectedイベントはStartSessionAsyncが返る前に発生するため、呼び出しの完了後にConversationIdとStatusを直接読み取ってください。パッケージの変更履歴には、すべてのイベント一覧が記載されています。

メソッド

メソッド説明
EndSession()接続を閉じ、オーディオデバイスを解放します。
SendUserMessage(string text)プレイヤーが発話したかのようにテキストメッセージを送信します。
SendContextualUpdate(string text)会話を中断せずにゲームの状態をエージェントと共有します。
SendUserActivity()プレイヤーがアクティブであることを通知し、エージェントがターンを維持します。
SendFeedback(bool like)CanSendFeedbackがtrueの場合に、最新のエージェント応答を評価します。
SetMicMuted(bool isMuted)マイクをミュートまたはミュート解除します。
SetVolume(float volume)エージェントの再生音量を0から1の範囲で設定します。
GetInputVolume(), GetOutputVolume()現在のマイクまたはエージェントのオーディオレベルを0から1の範囲で取得します。
GetInputByteFrequencyData(), GetOutputByteFrequencyData()オーディオビジュアライザー用の周波数データをバイトバッファに入力します。
UploadFileAsync(), SendMultimodalMessage()ファイルをアップロードし、ユーザーメッセージに添付します。
ChangeInputDevice(), ChangeOutputDevice()セッション中にマイクまたは出力デバイスを切り替えます。

たとえば、プレイヤーが新しいエリアに入ったとき、現在地をエージェントに送信します。

conversation.SendContextualUpdate("The player entered the abandoned lighthouse.");

WebGLビルド

WebGLビルドには、追加のPlayer Settingが1つ必要です。Player Settings > WebGL > Publishing Settingsで、Use WebAssembly.Tableをオンにします。この設定がオフの場合、SDKは手順を表示してビルドを失敗させます。

UnityにはWebGL用のスクリプタブルオーディオパイプラインがないため、SDKはブラウザのWeb Audio APIを通じてエージェントの音声を再生し、OutputAudioSourceの音量、位置、空間設定を反映します。そのため、WebGLではAudioSource.GetOutputDataとOnAudioFilterReadは無音を返します。代わりにGetOutputVolume()とGetOutputByteFrequencyData()を使用してください。

アクティブなビルドターゲットがWebGLの場合、EditorのPlay Modeはまだサポートされていません。Editorでテストするには、デスクトップビルドターゲットに切り替えてください。

WebGLの完全な互換性マトリクスについては、COMPATIBILITY.mdを参照してください。

トラブルシューティング

  • StartSessionAsyncがArgumentExceptionをスローする。 AgentId、SignedUrl、ConversationTokenのいずれか1つだけを設定してください。
  • 有効なエージェントIDでセッション接続に失敗する。 エージェントに認証が必要です。認証をオフにするか、署名付きURLで接続してください。
  • オーバーライドが反映されない。 エージェントのSecurity設定で対応するオーバーライドを有効にしてください。
  • WebGLでプレイヤーに音が聞こえない。 ブラウザは、プレイヤーがページを操作するまでオーディオを停止したままにします。クリックまたはキー操作の後にセッションを開始してください。
  • WebGLでマイクを利用できない。 ブラウザは、HTTPSまたはlocalhostから配信されるページにのみマイクアクセスを許可します。

バグの報告や機能リクエストは、GitHubで受け付けています。