> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Unity SDK

> **Info**
>
> ElevenAgents의 작동 방식은 [ElevenAgents 개요](/docs/ko/eleven-agents/overview)를 참조하세요.

[ElevenAgents Unity SDK](https://github.com/elevenlabs/unity)는 Unity 씬을 ElevenLabs 에이전트에 연결합니다. 플레이어의 마이크를 캡처하고, 에이전트의 음성을 `AudioSource`를 통해 다시 스트리밍하며, Editor, 데스크톱 독립형 플레이어 및 WebGL 빌드에서 동일하게 작동하는 단일 `Conversation` API를 통해 세션을 제공합니다.

## 요구 사항

* Unity 6.3 LTS (`6000.3.0f1`) 이상. SDK는 Unity 6.3에서 도입된 스크립터블 오디오 API를 사용합니다.
* **Api Compatibility Level**을 Unity 2023.1 이상 기본값인 **.NET Standard 2.1**로 설정합니다.
* ElevenLabs 계정과 에이전트. [대시보드](https://elevenlabs.io/app/agents)에서 생성하거나 [빠른 시작](/docs/ko/eleven-agents/quickstart)을 따르세요.

### 플랫폼 지원

| 대상                                                 | 전송 방식                           | 상태                      |
| -------------------------------------------------- | ------------------------------- | ----------------------- |
| Editor(Play Mode), 데스크톱 독립형(macOS, Windows, Linux) | 네이티브 WebSocket                  | 지원됨                     |
| WebGL                                              | JS 브리지를 통한 `@elevenlabs/client` | 지원됨(WebSocket 및 WebRTC) |
| iOS, Android, XR                                   | 네이티브 WebSocket                  | 테스트되지 않음                |

SDK는 활성 빌드 대상에 맞는 전송 방식을 자동으로 선택합니다. WebRTC는 WebGL에서만 사용할 수 있으며, 다른 모든 대상에서 `ConnectionType.WebRTC`는 `NotSupportedException`을 발생시킵니다.

> **Note**
>
> SDK는 마이크 권한을 요청하지 않습니다. iOS 및 Android에서는 세션을 시작하기 전에 직접 권한을 요청하세요.

## 설치

Unity에서 **Window** > **Package Manager**를 열고 **+** > **Install package from git URL**를 선택한 다음, 리포지토리 URL을 붙여넣으세요.

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

Package Manager가 의존성인 Input System 및 Newtonsoft Json과 함께 **ElevenAgents** 패키지(`io.elevenlabs.agents`)를 설치합니다.

> **Tip**
>
> 패키지에는 두 개의 샘플이 포함되어 있습니다. **Package Manager** > **ElevenAgents** >
> **Samples**에서 가져오세요. **QuickStart**는 실시간 트랜스크립트를 렌더링하는 단일 MonoBehaviour입니다.
> **GettingStarted**는 공간 오디오와 동적 변수가 포함된 다가가서 대화하는 씬입니다. 단계별 안내는
> [시작하기 가이드](https://github.com/elevenlabs/unity/blob/main/Docs~/GETTING_STARTED.md)를 참조하세요.

## 빠른 시작

이 섹션에서는 빈 씬에 음성 에이전트를 추가합니다. Play Mode에 진입하면 에이전트가 대화를 시작하고, 종료하면 세션도 끝납니다.

#### 공개 에이전트 만들기

[ElevenLabs 대시보드](https://elevenlabs.io/app/agents)에서 에이전트를 만드세요. 에이전트의 **Security** 설정에서 게임이 에이전트 ID만으로 연결할 수 있도록 **Authentication**을 끄세요. 에이전트 ID를 복사합니다.

인증이 필요한 에이전트는 [공개 및 비공개 에이전트](#public-and-private-agents)를 참조하세요.

#### SDK 설치

[설치](#installation)에 설명된 대로 git URL에서 패키지를 설치하세요.

#### 대화 스크립트 추가

`Assets/Scripts/AgentConversation.cs`를 만드세요.

**`AgentConversation.cs`**

```csharp title="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`에서 호출해도 안전합니다.

#### 씬 실행

빈 GameObject를 만들고 `AgentConversation` 컴포넌트를 추가한 다음, **Agent Id** 필드에 에이전트 ID를 붙여넣으세요. Play Mode에 진입하고 운영 체제에서 요청하면 마이크 액세스를 허용하세요. 에이전트가 첫 메시지를 말하고 트랜스크립트가 Console에 표시됩니다.

## 공개 및 비공개 에이전트

#### 공개 에이전트

에이전트 ID를 직접 전달하세요. ID를 아는 사람은 누구나 에이전트와 대화를 시작할 수 있습니다.

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

#### 비공개 에이전트

인증이 활성화된 에이전트에는 자체 서버에서 발급한 단기 자격 증명이 필요합니다. 백엔드에서 [서명된 URL](/docs/ko/eleven-agents/customization/authentication)을 요청하고 `SignedUrl`로 전달하세요.

```csharp
using UnityEngine.Networking;

private static async Awaitable<string> FetchSignedUrlAsync()
{
    using var request = UnityWebRequest.Get("https://api.example-game.com/agent/signed-url");
    await request.SendWebRequest();
    if (request.result != UnityWebRequest.Result.Success)
        throw new InvalidOperationException(request.error);
    return request.downloadHandler.text;
}

var conversation = await Conversation.StartSessionAsync(
    new ConversationOptions { SignedUrl = await FetchSignedUrlAsync() }
);
```

WebGL의 WebRTC 세션에서는 대화 토큰을 `ConversationToken`으로 전달하고 `ConnectionType = ConnectionType.WebRTC`를 설정하세요.

> **Warning**
>
> 게임 빌드에 ElevenLabs API 키를 절대 포함하지 마세요. 직접 관리하는 서버에서 서명된 URL과 대화 토큰을 생성하세요.

`AgentId`, `SignedUrl`, `ConversationToken` 중 정확히 하나를 설정하세요. 자체 시스템에서 대화를 플레이어와 연결하려면 `UserId`를 설정하세요.

## 공간 오디오

기본적으로 SDK는 생성한 숨겨진 `AudioSource`를 통해 에이전트 음성을 재생합니다. 씬에 음성을 배치하려면 자체 `AudioSource`를 `OutputAudioSource`로 전달하세요.

```csharp
[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 사이의 값을 반환합니다.

## 개인화

[동적 변수](/docs/ko/eleven-agents/customization/personalization/dynamic-variables)를 사용해 에이전트 프롬프트와 첫 메시지의 플레이스홀더를 채우고, [재정의](/docs/ko/eleven-agents/customization/personalization/overrides)를 사용해 단일 세션의 에이전트 구성 일부를 교체하세요.

```csharp
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** 설정에서 활성화해야 합니다.

## 클라이언트 도구

[클라이언트 도구](/docs/ko/eleven-agents/customization/tools/client-tools)를 사용하면 에이전트가 게임에서 작업을 실행할 수 있습니다. 에이전트 설정에서 도구를 정의한 다음 같은 이름의 핸들러를 등록하세요.

```csharp
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의 메인 스레드에서 이벤트를 발생시킵니다.

| 이벤트                       | 페이로드                   | 설명                                                     |
| ------------------------- | ---------------------- | ------------------------------------------------------ |
| `Disconnected`            | `DisconnectionDetails` | 세션이 종료되었습니다. `Reason`은 `User`, `Agent` 또는 `Error`입니다.  |
| `ErrorOccurred`           | `string`               | 세션 시작 후 오류가 발생했습니다.                                    |
| `StatusChanged`           | `Status`               | 연결 상태가 변경되었습니다.                                        |
| `ModeChanged`             | `Mode`                 | 에이전트가 `Speaking`과 `Listening` 사이를 전환했습니다.              |
| `UserTranscriptReceived`  | `UserTranscriptArgs`   | 플레이어 음성의 확정된 트랜스크립트입니다.                                |
| `AgentResponded`          | `AgentResponseArgs`    | 에이전트 응답의 텍스트입니다.                                       |
| `Interrupted`             | `InterruptionArgs`     | 플레이어가 에이전트를 중단했습니다.                                    |
| `AgentToolRequested`      | `AgentToolRequestArgs` | 에이전트가 도구 호출을 시작했습니다. 완료되면 `AgentToolResponded`가 발생합니다. |
| `UnhandledClientToolCall` | `ClientToolCallArgs`   | 에이전트가 등록된 핸들러가 없는 클라이언트 도구를 호출했습니다.                    |
| `CanSendFeedbackChanged`  | `bool`                 | 최신 에이전트 응답에 대한 피드백 제공 가능 여부가 변경되었습니다.                  |

`Connected` 이벤트는 `StartSessionAsync`가 반환되기 전에 발생하므로, 호출이 완료되면 `ConversationId`와 `Status`를 직접 읽으세요. 전체 이벤트 목록은 [패키지 변경 로그](https://github.com/elevenlabs/unity/blob/main/CHANGELOG.md)를 참조하세요.

## 메서드

| 메서드                                                           | 설명                                              |
| ------------------------------------------------------------- | ----------------------------------------------- |
| `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()`                 | 세션 중 마이크 또는 출력 장치를 전환합니다.                       |

예를 들어 플레이어가 새 지역에 진입할 때 현재 위치를 에이전트에 전송할 수 있습니다.

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

## WebGL 빌드

WebGL 빌드에는 추가 Player Setting 하나가 필요합니다. **Player Settings** > **WebGL** > **Publishing Settings**에서 **Use WebAssembly.Table**을 켜세요. 이 설정이 꺼져 있으면 SDK가 안내와 함께 빌드에 실패합니다.

Unity는 WebGL에서 스크립터블 오디오 파이프라인을 제공하지 않으므로, SDK는 브라우저의 Web Audio API를 통해 에이전트 음성을 재생하고 `OutputAudioSource`의 볼륨, 위치 및 공간 설정을 미러링합니다. 따라서 WebGL에서 `AudioSource.GetOutputData`와 `OnAudioFilterRead`는 무음을 반환합니다. 대신 `GetOutputVolume()`과 `GetOutputByteFrequencyData()`를 사용하세요.

> **Note**
>
> 활성 빌드 대상이 WebGL인 동안에는 Editor의 Play Mode가 아직 지원되지 않습니다. Editor에서 테스트하려면 데스크톱 빌드 대상으로 전환하세요.

전체 WebGL 호환성 매트릭스는 [`COMPATIBILITY.md`](https://github.com/elevenlabs/unity/blob/main/COMPATIBILITY.md)를 참조하세요.

## 문제 해결

* **`StartSessionAsync`가 `ArgumentException`을 발생시킵니다.** `AgentId`, `SignedUrl`, `ConversationToken` 중 정확히 하나를 설정하세요.
* **유효한 에이전트 ID로 세션 연결에 실패합니다.** 에이전트에 인증이 필요합니다. 인증을 끄거나 서명된 URL로 연결하세요.
* **재정의가 적용되지 않습니다.** 에이전트의 **Security** 설정에서 해당 재정의를 활성화하세요.
* **플레이어가 WebGL에서 아무 소리도 듣지 못합니다.** 브라우저는 플레이어가 페이지와 상호작용할 때까지 오디오를 일시 중지 상태로 유지합니다. 클릭 또는 키 입력 후 세션을 시작하세요.
* **WebGL에서 마이크를 사용할 수 없습니다.** 브라우저는 HTTPS 또는 `localhost`에서 제공되는 페이지에만 마이크 액세스를 허용합니다.

버그 신고 및 기능 요청은 [GitHub](https://github.com/elevenlabs/unity/issues)에서 하세요.