> For the complete documentation index, see [llms.txt](https://docs.gamechat.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gamechat.me/basics/game-chat-v2/game-chat-zhong-wen/qi-dong-game-chat/unity-sdk.md).

# Unity SDK

## 配置要求 <a href="#undefined" id="undefined"></a>

使用Game Chat Unity SDK时的配置要求如下。

* 最低配置：2018.4.0以上\
  （如需获得低版本Unity的支持，请在 '<cs@nbase.io>' 进行咨询。 )
* 2019.4.X/2020.3.X/2021.1.X版本的Unity编辑器用户请使用2019.4.29f1以上/2020.3.15f2以上/2021.1.16f1以上版本（构建AAB版本时存在的Unity编辑器漏洞被修复的版本）。

## 验证

#### 重置Game Chat实例 <a href="#gamechat" id="gamechat"></a>

如需使用Game Chat项目ID重置Game Chat实例，请使用下列代码：

```csharp
GameChat.initialize(PROJECT_ID);

// 使用新加坡区域时
GameChat.setRegion("sg");
GameChat.initialize(PROJECT_ID);
```

| ID          | type   | desc |
| ----------- | ------ | ---- |
| PROJECT\_ID | string | 项目ID |

### 连接Game Chat Socket服务器

#### 连接Game Chat Socket服务器的方法如下：

1. 使用聊天用户ID访问Game Chat Socket服务器。
   * Game Chat项目中，聊天用户ID是唯一值。
2. 获取使用API所需的Token值。
   * 可查看GameChat.connect之后更新的Token值。
3. 获取Token值后确认当前访问设备的聊天用户信息是否已更新。
   * 通过回调GameChat.connect获取的会员信息为更新后的数据。

### 如需连接Game Chat Socket服务器，请使用下列代码：

```csharp
GameChat.connect(USER_ID,  (Member User, GameChatException Exception)=> 
{

    if(Exception != null)
    {
        // 错误处理
        return;
    }
});
```

| ID       | type   | desc     |
| -------- | ------ | -------- |
| USER\_ID | string | 聊天用户唯一ID |

### 断开Game Chat服务器连接 <a href="#gamechat" id="gamechat"></a>

如需断开与Game Chat Socket服务器的连接，请使用下列代码：

```csharp
GameChat.disconnect();
```

### 更新聊天用户信息 <a href="#undefined" id="undefined"></a>

连接成功后，如需保存并更新聊天用户信息，请使用下列代码。

#### **修改昵称**

```csharp
GameChat.setNickname(USER_ID, NickName, (member, exception) =>
{
    if (exception != null)
    {
        // 错误处理
        return;
    }
    
});
```

<table><thead><tr><th width="206">ID</th><th width="169">type</th><th>desc</th></tr></thead><tbody><tr><td>USER_ID</td><td>string</td><td>聊天用户唯一ID</td></tr><tr><td>NickName</td><td>string</td><td>聊天用户昵称</td></tr></tbody></table>

#### **修改简介URL**

```csharp
GameChat.setProfileUrl(USER_ID, ProfileUrl, (member, exception) =>
{
    if (exception != null)
    {
        // 错误处理
        return;
    }
    
});
```

<table><thead><tr><th width="210">ID</th><th width="169">type</th><th>desc</th></tr></thead><tbody><tr><td>USER_ID</td><td>string</td><td>聊天用户唯一ID</td></tr><tr><td>ProfileUrl</td><td>string</td><td>聊天用户ProfileURL</td></tr></tbody></table>

## 订阅和取消订阅频道

如需订阅或取消订阅特定频道，请使用下列代码：

```csharp
GameChat.subscribe(CHANNEL_ID);

GameChat.unsubscribe(CHANNEL_ID);
```

| ID          | type   | desc |
| ----------- | ------ | ---- |
| CHANNEL\_ID | string | 频道ID |

## 发送消息 <a href="#undefined" id="undefined"></a>

如需向特定频道发送消息，请使用下列代码：

```csharp
GameChat.sendMessage(CHANNEL_ID, MESSAGE);
```

<table><thead><tr><th width="220">ID</th><th width="160">type</th><th>desc</th></tr></thead><tbody><tr><td>CHANNEL_ID</td><td>string</td><td>频道ID</td></tr><tr><td>MESSAGE</td><td>string</td><td>发送的消息文本</td></tr></tbody></table>

在消息参数中输入@\[玩家ID]空格\[消息内容]时

```csharp
@user_id消息正文
```

在上述用例中，如果玩家ID已有登录历史，消息详细信息中提及的信息即为玩家ID。

## 添加和解除事件

如需对从Game Chat Socket服务器接收的事件添加或解除自定义处理，请使用下列代码：

```csharp
GameChat.dispatcher.(EVENT_NAME) += (CALLBACK_FUNCTION);
```

```csharp
public delegate void onConnectedCallback(string data);
public onConnectedCallback onConnected;
对//“connect”事件的回调

public delegate void onDisconnectedCallback(string reason);
public onDisconnectedCallback onDisconnected;
对//“disconnect”事件的回调

public delegate void onMessageReceivedCallback(Message message);
public onMessageReceivedCallback onMessageReceived;
对//“message”事件的回调

public delegate void onUserAddedCallback(UserInfo userinfo);
public onUserAddedCallback onUserAdded;
对//“userAdded”事件的回调

public delegate void onUserRemovedCallback(Message message);
public onUserRemovedCallback onUserRemoved;
对//“userRemoved”事件的回调

public delegate void onErrorReceivedCallback(string result, GameChatException exception);
public onErrorReceivedCallback onErrorReceived;
对//“error”事件的回调
```

## 例外情形

下面是对使用Game Chat API过程中发生的例外情况采取的通用处理Class。

<pre class="language-csharp"><code class="lang-csharp"><strong>public class GameChatException
</strong>{
    // Detail Error Code
   
    // 未知错误
    public static readonly int CODE_UNKNOWN_ERROR           = 0;
    // 初始化失败
    public static readonly int CODE_NOT_INITALIZE           = 1;
    // 参数不正确时
    public static readonly int CODE_INVAILD_PARAM           = 2;  
    // Socket服务器发生错误
    public static readonly int CODE_SOCKET_SERVER_ERROR     = 500;
    // Socket发生错误
    public static readonly int CODE_SOCKET_ERROR = -501;
    // 发生网络连接错误及超时时
    public static readonly int CODE_SERVER_NETWORK_ERROR    = 4002;
    // 解析从服务器接收的数据时发生错误
    public static readonly int CODE_SERVER_PARSING_ERROR    = 4003;

    // 发生HTTP错误时，传递相应状态码作为响应代码。 (400, 403 ...)

    // Error Code
    public int code { get; set; }
    // Error Message
    public string message { get; set; }
}
</code></pre>

## Client API

### 订阅频道

#### **Subscription Data Class (per Unit)**

```csharp
public class Subscription
{
    public string id;
    public string channel_id;
    public string user_id;
    public string created_at;
}
```

<table><thead><tr><th width="173">ID</th><th width="186">type</th><th>desc</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>唯一ID</td></tr><tr><td>channel_id</td><td>string</td><td>频道ID</td></tr><tr><td>user_id</td><td>string</td><td>聊天用户唯一ID</td></tr><tr><td>created_at</td><td>string</td><td>创建日期</td></tr></tbody></table>

#### **导入频道订阅列表**

如需以列表形式导入特定频道的订阅数据，请使用下列代码：

```csharp
GameChat.getSubscriptions(CHANNEL_ID, OFFSET, LIMIT, (List<Subscription> Subscriptions, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    foreach(Subscription elem in Subscriptions)
    {
        //handling each subscription instance
    }
}));
```

### 频道

#### **Channel Data Class (per Unit)**

```csharp
public class Channel
{
    public string id;
    public string project_id;
    public string unique_id;
    public string name;
    public string user_id;
    public string created_at;
    public string updated_at;
}
```

<table><thead><tr><th width="193">ID</th><th width="172">type</th><th>desc</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>频道ID（唯一值）</td></tr><tr><td>project_id</td><td>string</td><td>项目ID</td></tr><tr><td>unique_id</td><td>string</td><td>开发公司可设置的频道ID（唯一值）</td></tr><tr><td>name</td><td>string</td><td>频道名称</td></tr><tr><td>user_id</td><td>string</td><td>（创建频道的）聊天用户ID</td></tr><tr><td>created_at</td><td>string</td><td>创建日期</td></tr><tr><td>updated_at</td><td>string</td><td>更新日期</td></tr></tbody></table>

#### **导入频道列表**

如需以列表形式导入项目的频道数据，请使用下列代码：

```csharp
GameChat.getChannels(OFFSET, LIMIT, (List<Channel> Channels, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    foreach(Channel elem in Channels)
    {
        //handling each channelInfo instance
    }
});
```

<table><thead><tr><th width="185">ID</th><th width="134">type</th><th>desc</th></tr></thead><tbody><tr><td>OFFSET</td><td>int</td><td>拟从全部频道列表导入的频道的开始位置（索引）</td></tr><tr><td>LIMIT</td><td>int</td><td>拟导入的频道数量</td></tr></tbody></table>

#### **导入频道数据**

如需使用频道ID和唯一ID导入频道数据，请使用下列代码：

```csharp
仅使用//CHANNEL_ID搜索时，在CHANNEL_UNIQUE_ID参数中输入null。

//CHANNEL_ID和CHANNEL_UNIQUE_ID值同时存在时，优先搜索CHANNEL_UNIQUE_ID值。

GameChat.getChannel(CHANNEL_ID, CHANNEL_UNIQUE_ID,  (Channel Channel, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    //handling channelInfo instance
});
```

```csharp
GameChat.getChannel(CHANNEL_UNIQUE_ID, (Channel Channel, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    //handling channelInfo instance
});
```

| ID                  | type   | desc           |
| ------------------- | ------ | -------------- |
| CHANNEL\_ID         | string | 频道ID（自动生成）     |
| CHANNEL\_UNIQUE\_ID | string | 频道（唯一）ID（可自定义） |

### 创建和删除频道 <a href="#undefined" id="undefined"></a>

如需在项目内创建和删除新的频道，应使用Open API。\
考虑到安全问题，建议使用Open API通过Server to Server手动进行频道创建和更新等操作。 详细内容请参考Game Chat API指南。

### 消息 <a href="#undefined" id="undefined"></a>

**(Received) Message Data Class (per Unit)**

```csharp
public class Message
{
    public class User
    {
        public string id;
        public string name;
        public string profile;
    }

    public string message_id;
    public string channel_id;
    public string message_type;
    public string content;

    public string[] mentions;
    public bool mentions_everyone;
    public User sender;
    public string created_at;
}
```

<table><thead><tr><th width="195">ID</th><th width="140">type</th><th>desc</th></tr></thead><tbody><tr><td>message_id</td><td>string</td><td>消息的唯一ID</td></tr><tr><td>channel_id</td><td>string</td><td>频道ID</td></tr><tr><td>message_type</td><td>string</td><td>消息类型</td></tr><tr><td>content</td><td>string</td><td>消息内容（JSON字符串）</td></tr><tr><td>mentions</td><td>string</td><td>提及（标签）</td></tr><tr><td>created_at</td><td></td><td>string</td></tr></tbody></table>

#### **导入消息列表**

如需以列表形式导入特定频道的消息数据，请使用下列代码：

```csharp
GameChat.getMessages(CHANNEL_ID, OFFSET, LIMIT, SEARCH, QUERY, SORT, (List<Message> Messages, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    foreach(Message elem in Messages)
    {
        //handling each message instance
    }
});
```

<table><thead><tr><th width="190">ID</th><th width="125">type</th><th>desc</th></tr></thead><tbody><tr><td>CHANNEL_ID</td><td>string</td><td>频道ID</td></tr><tr><td>OFFSET</td><td>string</td><td>拟从全部消息列表导入的消息的开始位置</td></tr><tr><td>LIMIT</td><td>string</td><td>拟导入的消息数量</td></tr><tr><td>SEARCH</td><td>string</td><td>消息搜索基准参数； &#x3C;示例> content.text<br>传递空字符串时，全数扫描</td></tr><tr><td>QUERY</td><td>string</td><td>消息搜索值； 只能搜索完全一致的内容。 传递空字符串时，全数扫描</td></tr><tr><td>SORT</td><td>string</td><td>消息排列顺序（默认：降序 - 按最新排列）（可选项：升序）</td></tr></tbody></table>

#### **翻译消息**

自动翻译功能被激活的状态下，可将任意文本翻译成指定语言。 关联[Papago Translation](https://www.ncloud.com/product/aiService/papagoTranslation){target="\_blank"}服务后即可使用自动翻译功能。

**(Received) Translation Data Class (per Unit)**

```csharp
public class Translation
{
    public string detectLang = "";
    public string lang = "";
    public bool translated = false;
    public string message = "";
}
```

<table><thead><tr><th width="177">ID</th><th width="141">type</th><th>desc</th></tr></thead><tbody><tr><td>detectLang</td><td>string</td><td>源语言代码</td></tr><tr><td>lang</td><td>string</td><td>目标语言代码</td></tr><tr><td>translated</td><td>bool</td><td>是否翻译成功</td></tr><tr><td>message</td><td>string</td><td>结果消息内容（JSON字符串）</td></tr></tbody></table>

> &#x20;参考
>
> 关于源语言代码和目标语言代码的介绍，请参考[Papago Text Translation API指南](https://api.ncloud-docs.com/docs/zh/ai-naver-papagonmt-translation)

```csharp
GameChat.translateMessage(CHANNEL_ID, SORCE_LANG, TARTGET_LANG, TEXT, (List<Translation> Translations, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    foreach(Translation elem in Translations)
    {
        //handling each Translation instance
    }
});

GameChat.translateMessage(SORCE_LANG, TARTGET_LANG, TEXT, (List<Translation> Translations, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }

    foreach(Translation elem in Translations)
    {
        //handling each Translation instance
    }
});
```

<table><thead><tr><th width="187">ID</th><th width="108">type</th><th>desc</th></tr></thead><tbody><tr><td>CHANNEL_ID</td><td>string</td><td>频道ID</td></tr><tr><td>SORCE_LANG</td><td>string</td><td>拟发送的文本语言名称（auto：自动检测）<br>参考<a href="https://api.ncloud-docs.com/docs/zh/ai-naver-papagonmt-translation">API指南</a>{target="_blank"}</td></tr><tr><td>TARTGET_LANG</td><td>string</td><td>（待接收翻译的）文本语言代码<br>（可使用“,”符号隔开输入多个。 &#x3C;示例> “en, fr, th”）<br>参考<a href="https://api.ncloud-docs.com/docs/zh/ai-naver-papagonmt-translation">Papago Text Translation API指南</a>{target="blank"}</td></tr><tr><td>TEXT</td><td>string</td><td>拟发送的文本</td></tr></tbody></table>

### 聊天用户 <a href="#undefined" id="undefined"></a>

**(Received) Member Data Class (per Unit)**

```csharp
public class Member
{
    public string id = "";
    public string project_id = "";
    public string nickname = "";
    public string profile_url = "";
    public string country = "";
    public string remoteip = "";
    public string adid = "";
    public string device = "";
    public string network = "";
    public string version = "";
    public string model = "";
    public string logined_at = "";
    public string created_at = "";
    public string updated_at = "";
}
```

<table><thead><tr><th width="187">ID</th><th width="127">type</th><th>desc</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>聊天用户唯一ID</td></tr><tr><td>project_id</td><td>string</td><td>已登录的Game Chat项目ID</td></tr><tr><td>nickname</td><td>string</td><td>聊天用户昵称</td></tr><tr><td>profile_url</td><td>string</td><td>头像图片URL</td></tr><tr><td>country</td><td>string</td><td>访问国家</td></tr><tr><td>remoteip</td><td>string</td><td>访问IP</td></tr><tr><td>adid</td><td>string</td><td>广告标识符</td></tr><tr><td>device</td><td>string</td><td>访问设备环境</td></tr><tr><td>network</td><td>string</td><td>访问网络类型（移动数据、Wi-Fi）</td></tr><tr><td>version</td><td>string</td><td>访问的应用版本</td></tr><tr><td>model</td><td>string</td><td>访问设备型号</td></tr><tr><td>logined_at</td><td>string</td><td>登录日期</td></tr><tr><td>created_at</td><td>string</td><td>聊天用户创建日期</td></tr><tr><td>updated_at</td><td>string</td><td>聊天用户信息更新日期</td></tr></tbody></table>

#### **更新聊天用户信息**

可更新聊天服务器的用户信息。

```csharp

// 更新聊天用户昵称
// 昵称可用的字符串长度为2~128个字符，不得包含空白字符（空格、制表符、换行符）。
GameChat.setName(MEMBER_ID, NAME, (Member member, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }
    //handling updated Member instance
});

//更新聊天用户简介图片URL
GameChat.setProfileUrl(MEMBER_ID, PROFILE_URL, (Member member, GameChatException Exception) => {

    if(Exception != null)
    {
        // 错误处理
        return;
    }
    //handling updated Member instance
});

```

<table><thead><tr><th width="190">ID</th><th width="153">type</th><th>desc</th></tr></thead><tbody><tr><td>MEMBER_ID</td><td>string</td><td>聊天用户唯一ID</td></tr><tr><td>NAME</td><td>string</td><td>聊天用户昵称或姓名</td></tr><tr><td>PROFILE</td><td>string</td><td>头像图片URL</td></tr></tbody></table>

## GameChatExtension (Emoji, HyperLink) <a href="#gamechatextensionemojihyperlink" id="gamechatextensionemojihyperlink"></a>

帮助开发人员轻松处理所接收消息中包含的表情符号和超链接文本的辅助类。

* TMP\_GameChatTextUGUI是对Unity内置资源TextMeshPro进行扩展的类，因此须先使用Package Manager安装TextMeshPro。
* TextMeshPro资源在Unity 2018.2以上版本中以内置资源形式提供。
* 表情符号的精灵表单默认以Emoji 13版本（Android）为基准进行输出，可通过更改精灵表单进行自定义设置。

```csharp
namespace GameChatUnity.Extension
{
    public class TMP_GameChatTextUGUI : TextMeshProUGUI
    {
        public bool isHyperLinked { get; set; }   // 是否对链接形式的地址进行超链接处理（添加HTML标签）
        public string LinkTextColor { get; set; }  // hyperlink text color
    }
}
```

**<示例>**

```csharp
using GameChatUnity.Extension;

TMP_GameChatTextUGUI message = msgObject.GetComponent<TMP_GameChatTextUGUI>();

//为了识别并处理超链接，需使用setMessage输入文本。
message.setMessage(MESSAGE_CONTENT);
message.color = Color.green;
message.isHyperLinked = true;

...

msgObject = Instantiate(msgObject) as GameObject;

...

// 对于超链接的click event listener需直接构建。

//Handling with TMP_LinkInfo
TMP_LinkInfo linkInfoArr = message.textInfo.linkInfo[LINK_INDEX];

...
```
