# 频道 (/zh-CN/api-reference/rtm/unity/channel)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

频道是 RTM 实时网络中一种数据传输的管理机制，任何订阅或加入频道的用户都可以在 100 毫秒内接收到频道中传输的消息和事件，RTM 允许客户端订阅数百甚至数千个频道。大多数 RTM API 都将以频道为基础进行发送、接收、加密等行为。

基于声网的能力，RTM 的频道分成两种类型以匹配不同的应用场景：

- Message Channel：遵循行业标准的 Pub/Sub （发布/订阅）模式，频道无需提前创建，订阅频道即可在频道内收发消息。频道内的发布者和订阅者数量没有上限。
- Stream Channel：遵循行业类似观察者模式的 Room （房间）概念，用户需要创建并加入频道才能在频道内收发消息。频道中允许创建不同的 Topic，消息通过 Topic 进行组织和管理。

想要了解 **Message** 和 **Stream** 频道的更多用法及适用场景，可以查看：

- [频道](/zh-CN/realtime-media/rtm/build/channels-and-topics/channel-basic)

## SubscribeAsync [#subscribeasync]

### 接口描述 [#接口描述]

RTM 提供消息、状态等事件通知能力。通过设置事件监听，你可以接收已订阅频道中的消息和事件。关于如何添加和设置事件监听，详见[事件监听](/zh-CN/api-reference/rtm/unity/configuration#事件监听)章节。

通过调用 `SubscribeAsync` 方法，客户端可以订阅 Message Channel 并开始接收频道中的消息和事件通知。成功调用该方法后，订阅该频道且开启 Presence 事件监听的用户会收到 `REMOTE_JOIN` 类型的 `OnPresenceEvent` 事件，详见[事件监听](/zh-CN/api-reference/rtm/unity/configuration#事件监听)。

:::info[信息]
该方法仅适用于 Message Channel。
:::

### 接口方法 [#接口方法]

你可以通过以下方式调用 `SubscribeAsync` 方法：

```csharp
RtmResult<SubscribeResult> SubscribeAsync(string channelName, SubscribeOptions options);
```

| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `channelName` | string | 必填 | - | 频道名称。 |
| `options` | `SubscribeOptions` | 选填 | - | 订阅频道选项。 |

`SubscribeOptions` 包含以下属性：

| 属性 | 类型 | 是否必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `withMessage` | bool | 选填 | true | 是否订阅此频道中的消息事件通知。 |
| `withPresence` | bool | 选填 | true | 是否订阅此频道中的 Presence 事件通知。 |
| `withMetadata` | bool | 选填 | false | 是否订阅此频道中的 Storage 事件通知。 |
| `withLock` | bool | 选填 | false | 是否订阅此频道中的 Lock 事件通知。 |

### 基本用法 [#基本用法]

```cs
var options = new SubscribeOptions();
options.withMessage = true;
options.withPresence = true;
var (status,response) = await rtmClient.SubscribeAsync("Chat_room", options);
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode:{1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
else
{
    Debug.Log(string.Format("Subscribe channel success! at Channel:{0}", response.ChannelName));
}
```

### 返回值 [#返回值]

`SubscribeAsync` 操作返回一个 `RtmResult<SubscribeResult>` 类型数据结构的返回值，其中包含：

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `Status` | `RtmStatus` | 无论操作是否成功，都返回一个 `RtmStatus` 类型的数据结构，其中包含本次操作的状态。 |
| `Response` | `SubscribeResult` | 操作成功后，返回一个 `SubscribeResult` 类型的数据结构，其中包含本次操作的执行结果。 |

`RtmStatus` 包含以下属性：

|    属性     |  类型  | 描述               |
| ------- | -- | ------- |
|   `Error`   |  bool  | 本次操作是否出错。 |
| `ErrorCode` | string | 错误码             |
| `Operation` | string | 本次操作类型。     |
|  `Reason`   | string | 本次操作出错原因。 |

你可以通过检索 `errorCode` 字段的[错误码](/zh-CN/realtime-media/rtm/build/troubleshooting)了解错误原因，并找到对应的解决方法。

`SubscribeResult` 包含以下属性：

| 属性          |  类型  | 描述                       |
| ------------ | --- | ----------- |
| `ChannelName` | string | Message Channel 频道名称。 |

## UnsubscribeAsync [#unsubscribeasync]

### 接口描述 [#接口描述-1]

如果你不再需要关注某个频道，可调用 `UnsubscribeAsync` 方法取消订阅该频道。成功取消订阅该频道后，其他订阅该频道并开启事件监听的用户会收到 `REMOTE_LEAVE` 类型的 `OnPresenceEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/unity/configuration#事件监听)。

:::info[信息]
该方法仅适用于 Message Channel。
:::

### 接口方法 [#接口方法-1]

你可以通过以下方式调用 `UnsubscribeAsync` 方法：

```cs
RtmResult<UnsubscribeResult> UnsubscribeAsync(string channelName);
```

|     参数      |  类型  | 是否必填 | 默认值 | 描述       |
| ---------- | --- | ----- | --- | ---------- |
| `channelName` | string |   必填   |   -    | 频道名称。 |

### 基本用法 [#基本用法-1]

```csharp
var (status,response) = await rtmClient.UnsubscribeAsync(channelName);
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode: {1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
```

### 返回值 [#返回值-1]

`UnsubscribeAsync` 操作返回一个 `RtmResult<UnsubscribeResult>` 类型数据结构的返回值，其中包含：

|    属性    |         类型          | 描述                   |
| ------- | ------ | ----------- |
|  `Status`  |     `RtmStatus`      | 无论操作是否成功，都返回一个 `RtmStatus` 类型的数据结构，其中包含本次操作的状态。                     |
| `Response` | `UnsubscribeResult` | 操作成功后，返回一个 `UnsubscribeResult` 类型的数据结构，当前不包含任何数据，用户可以忽略。 |

`RtmStatus` 包含以下属性：

|    属性     |  类型  | 描述               |
| ------- | -- | ------- |
|   `Error`   |  bool  | 本次操作是否出错。 |
| `ErrorCode` | string | 错误码             |
| `Operation` | string | 本次操作类型。     |
|  `Reason`   | string | 本次操作出错原因。 |

你可以通过检索 `errorCode` 字段的[错误码](/zh-CN/realtime-media/rtm/build/troubleshooting)了解错误原因，并找到对应的解决方法。

## CreateStreamChannel [#createstreamchannel]

### 接口描述 [#接口描述-2]

在使用 Stream Channel 之前，你需要先调用 `CreateStreamChannel` 方法创建 `IStreamChannel` 实例。成功创建实例后，你可以调用其相关方法，例如：加入频道、离开频道、发送 Topic 消息、订阅 Topic 消息等。

:::info[信息]
该方法仅适用于 Stream Channel。
:::

### 接口方法 [#接口方法-2]

你可以通过以下方式调用 `CreateStreamChannel` 方法：

```csharp
IStreamChannel CreateStreamChannel(string channelName);
```

|     参数      |  类型  | 是否必填 | 默认值 | 描述       |
| ---------- | --- | ----- | --- | ---------- |
| `channelName` | string |   必填   |   -    | 频道名称。 |

### 基本用法 [#基本用法-2]

```csharp
try
{
    IStreamChannel streamChannel = rtmClient.CreateStreamChannel("Chat_room");
}
catch(RTMException e)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode : {1}, due to: {2}", e.Status.Operation, e.Status.ErrorCode, e.Status.Reason));
}
```

### 返回值 [#返回值-2]

一个 `IStreamChannel` 实例。

## JoinAsync [#joinasync]

### 接口描述 [#接口描述-3]

成功创建 Stream Channel 后，你可以调用 `JoinAsync` 方法加入 Stream Channel。

加入频道后，你才能进行频道相关操作。此时，订阅该频道并添加事件监听的用户会收到如下事件通知：

- 本地用户：
  - `SNAPSHOT` 类型的 `OnPresenceEvent` 事件通知。
  - `SNAPSHOT` 类型的 `OnTopicEvent` 事件通知。
- 远端用户：`REMOTE_JOIN` 类型的 `OnPresenceEvent` 事件通知。

:::info[信息]
该方法仅适用于 Stream Channel。
:::

### 接口方法 [#接口方法-3]

你可以通过以下方式调用 `JoinAsync` 方法：

```csharp
RtmResult<JoinResult> JoinAsync(JoinChannelOptions options);
```

|   参数   |          类型          | 是否必填 | 默认值 | 描述           |
| ----- | ------- | ----- | --- | ------------- |
| `option` | `JoinChannelOptions` |   选填   |   -    | 加入频道选项。 |

`JoinChannelOptions` 中包含以下属性：

| 属性 | 类型 | 是否必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `token` | string | 选填 | - | [channel-unity-html-3-1-4 details](#table-slot-channel-unity-html-3-1-4) |
| `withMetadata` | bool | 选填 | false | 是否订阅此频道中的 Storage 事件通知。 |
| `withPresence` | bool | 选填 | true | 是否订阅此频道中的 Presence 事件通知。 |
| `withLock` | bool | 选填 | false | 是否订阅此频道中的 Lock 事件通知。 |

<a id="table-slot-channel-unity-html-3-1-4"></a>

**channel-unity-html-3-1-4 details**

加入 Stream Channel 的 Token。

- 如果你的项目开启了 Token 鉴权，你可以填入 [RTC 临时 Token](/zh-CN/realtime-media/rtc/build/setup-and-access/enable-service#获取临时-token) 或 Token 服务器生成的 [RTC 正式 Token](/zh-CN/realtime-media/rtc/build/setup-and-access/token-authentication)。
- 如果你的项目未开启 Token 鉴权，你可以不填，或填入开通了 RTC 和 RTM 服务的项目 App ID。

### 基本用法 [#基本用法-3]

```cs
var (status,response) = await streamChannel.JoinAsync(options);
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrrorCode: {1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
else
{
    Debug.Log(string.Format("User:{0} Join stream channel success! at Channel:{1}", response.UserId, response.ChannelName));
}
```

### 返回值 [#返回值-3]

`JoinAsync` 操作返回一个 `RtmResult<JoinResult>` 类型数据结构的返回值，其中包含：

|  属性  |        类型         | 描述               |
| ----------- | ---------------- | ------ |
| `Status`      |      `RtmStatus`      | 无论操作是否成功，都返回一个 `RtmStatus` 类型的数据结构，其中包含本次操作的状态。 |
| `Response`      | `JoinResult` | 操作成功后，返回一个 `JoinResult` 类型的数据结构。 |

`RtmStatus` 包含以下属性：

|    属性     |  类型  | 描述               |
| ------- | -- | ------- |
|   `Error`   |  bool  | 本次操作是否出错。 |
| `ErrorCode` | string | 错误码             |
| `Operation` | string | 本次操作类型。     |
|  `Reason`   | string | 本次操作出错原因。 |

你可以通过检索 `errorCode` 字段的[错误码](/zh-CN/realtime-media/rtm/build/troubleshooting)了解错误原因，并找到对应的解决方法。

`JoinResult` 包含以下属性：

| 属性          |  类型  | 描述                       |
| ------------ | --- | ----------- |
| `ChannelName` | string | Message Channel 频道名称。 |
| `UserId`      | string | 用户 ID。                  |

## LeaveAsync [#leaveasync]

### 接口描述 [#接口描述-4]

如果你不再需要待在某个频道中，你可以调用 `LeaveAsync` 方法离开该频道。离开后你将不再会接收到此频道中的任何消息、状态及事件通知，你在该频道中创建的 Topic 发布者的角色及你与所有 Topic 的订阅关系都将自动解除。如果想再次恢复之前的发布者角色和订阅关系，你需要调用 `JoinAsync` 方法再次进入该频道并自行调用 `JoinTopicAsync` 和 `SubscribeTopicAsync` 方法进行设置。

成功离开频道后，频道中的远端用户会收到 `REMOTE_LEAVE` 类型的 `OnPresenceEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/unity/configuration#事件监听)。

:::info[信息]
该方法仅适用于 Stream Channel。
:::

### 接口方法 [#接口方法-4]

你可以通过以下方式调用 `LeaveAsync` 方法：

```csharp
RtmResult<LeaveResult> LeaveAsync();
```

### 基本用法 [#基本用法-4]

```csharp
var (status,response) = await streamChannel.LeaveAsync();
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode:{1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
else
{
    Debug.Log(string.Format("User:{0} Join stream channel success! at Channel:{1}", response.UserId, response.ChannelName));
}
```

### 返回值 [#返回值-4]

`LeaveAsync` 操作返回一个 `RtmResult<LeaveResult>` 类型数据结构的返回值，其中包含：

|  属性  |        类型         | 描述               |
| ----------- | ---------------- | ------ |
| `Status`      |      `RtmStatus`      | 无论操作是否成功，都返回一个 `RtmStatus` 类型的数据结构，其中包含本次操作的状态。|
| `Response`      | `LeaveResult` | 操作成功后，返回一个 `LeaveResult` 类型的数据结构，其中包含本次操作的细节信息。 |

`RtmStatus` 包含以下属性：

|    属性     |  类型  | 描述               |
| ------- | -- | ------- |
|   `Error`   |  bool  | 本次操作是否出错。 |
| `ErrorCode` | string | 错误码             |
| `Operation` | string | 本次操作类型。     |
|  `Reason`   | string | 本次操作出错原因。 |

你可以通过检索 `errorCode` 字段的[错误码](/zh-CN/realtime-media/rtm/build/troubleshooting)了解错误原因，并找到对应的解决方法。

`LeaveResult` 包含以下属性：

|     属性      |  类型  | 描述                       |
| ---------- | --- | ----------- |
| `ChannelName` | string | Message Channel 频道名称。 |
|   `UserId`    | string | 用户 ID。                  |

## Dispose [#dispose]

### 接口描述 [#接口描述-5]

如果你不再需要某个频道，你可以调用 `Dispose` 方法销毁对应的 Stream Channel 实例以释放资源。调用 `Dispose` 方法销毁 Stream Channel 实例不会销毁该频道，后续可通过再次调用 `CreateStreamChannel` 和 `JoinAsync` 重新加入该频道。

:::info[信息]
- 该方法仅适用于 Stream Channel。如果不先调用 `LeaveAsync` 离开频道而直接调用 `Dispose` 销毁频道实例，SDK 会自动调用 `LeaveAsync` 并触发对应的事件。
- `Dispose` 需要在非回调内的子线程调用，避免在回调中执行。
:::

### 接口方法 [#接口方法-5]

你可以通过以下方式调用 `Dispose` 方法：

```csharp
RtmStatus Dispose();
```

### 基本用法 [#基本用法-5]

```csharp
var status = streamChannel.Dispose();
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode:{1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
else
{
    Debug.Log("Dispose Channel Success!");
}
```

### 返回值 [#返回值-5]

本次操作将返回一个 `RtmStatus` 数据结构的返回值。

`RtmStatus` 包含以下属性：

|    属性     |  类型  | 描述               |
| ------- | -- | ------- |
|   `Error`   |  bool  | 本次操作是否出错。 |
| `ErrorCode` | string | 错误码             |
| `Operation` | string | 本次操作类型。     |
|  `Reason`   | string | 本次操作出错原因。 |

你可以通过检索 `errorCode` 字段的[错误码](/zh-CN/realtime-media/rtm/build/troubleshooting)了解错误原因，并找到对应的解决方法。
