Unreal Engine(C++) 快速开始与功能指南
Unreal Engine(C++):前置条件、安装、Token、加入频道、发布订阅、事件、错误处理与排障;接口名与签名在构建时取自公开 SDK 接口定义。
Unreal Engine(C++)端是 IRtcEngine + IRtcEngineEventHandler 形状,方法名小写开头,与 Android/Windows 的 C++ 面一致。
前置条件
- Unreal Engine 5.2+(C++ 工程,需要在
.uproject里启用插件)。 - 目标平台权限:Windows/macOS 系统摄像头麦克风权限;Android/iOS 见各自平台要求。
- 已拿到
appId与 Token 服务(见 控制台开通服务与获取凭证)。
安装
# 计划形态:把插件放到工程目录
YourGame/Plugins/NimeetRtc/…
# 重新生成工程文件后,在 .uproject 里启用 NimeetRtc 模块获取 Token
Token 由游戏后端签发,UE 客户端只接收字符串。生产形态是登录时下发短期 Token,并在 onTokenPrivilegeWillExpire 回调里请求续期;不要把 App Certificate 编进客户端。
加入频道
#include "NimeetRtc/IRtcEngine.h"
class FMeetingHandler final : public IRtcEngineEventHandler {
public:
void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed) override {}
void onUserJoined(uid_t uid, int elapsed) override {}
void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) override {}
void onTokenPrivilegeWillExpire(const char* token) override {}
void onError(int err, const char* msg) override {}
};
void UMeetingSubsystem::Start(const FString& AppId, const FString& Token)
{
Handler = MakeShared<FMeetingHandler>();
Engine = createAgoraRtcEngine();
RtcEngineContext Context;
Context.appId = TCHAR_TO_UTF8(*AppId);
Context.eventHandler = Handler.Get();
Engine->initialize(Context);
Engine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING);
Engine->enableVideo();
Engine->startPreview();
Engine->joinChannel(TCHAR_TO_UTF8(*Token), "weekly-sync", "", 10001);
}发布与订阅
Engine->muteLocalAudioStream(true);
Engine->muteLocalVideoStream(true);
Engine->enableLocalVideo(false);
Engine->updateChannelMediaOptions(Options);屏幕共享:getScreenCaptureSources → startScreenCaptureByDisplayId / startScreenCaptureByWindowId; 渲染远端画面用插件提供的 VideoSurface 组件(或自定义纹理回调)。
事件
IRtcEngineEventHandler 的 C++ 虚函数:onJoinChannelSuccess、onUserJoined、onUserOffline、 onFirstRemoteVideoDecoded、onTokenPrivilegeWillExpire、onError、onConnectionStateChanged。
错误处理
- 同步方法返回
int,0成功,负值为声网错误号; - 异步错误走
onError; - 未实现能力返回
-4(ERR_NOT_SUPPORTED)。
排障
| 现象 | 原因 | 处理 |
|---|---|---|
| 打包后找不到插件模块 | .uproject 未启用或未重新生成工程 | 启用模块并 Rebuild |
| 运行时崩溃在回调 | 跨线程访问 UObject | 用 AsyncTask 切回 GameThread |
| 摄像头无画面 | 平台权限未授予 | 系统设置授权后重启进程 |
| 远端画面不显示 | 未绑定 VideoSurface | 把 surface 绑到目标材质/控件 |
| 声音是单声道 | 音频设备配置 | 检查系统默认设备与采样率 |
下一步
平台信息
| 项 | 值 |
|---|---|
| 平台 | Unreal Engine(C++) |
| 语言 | C++ |
| SDK 包 | NimeetRtc |
| 接口版本 | 4.5.1 |
| 兼容参考 | 声网 unreal-cpp 端 API |
本端公开接口与声网 unreal-cpp 端 API 对齐;安装与运行要求见上面前置条件。
可用性
该端 SDK:正式可用。本页代码片段使用公开 API;运行时的能力边界以实际发布的 SDK 包为准。
加入频道链路
下列方法名、参数类型与返回值与同端 API 参考一致。一个平台若有多个重载,这里展示最常用的那一个;完整重载见同端 API 参考页。
| 步骤 | 接口 | 方法 | 重载数 |
|---|---|---|---|
| 订阅远端媒体 | IBaseSpatialAudioEngine | muteRemoteAudioStream | 1 |
| 创建实例 / 初始化 | ILocalSpatialAudioEngine | initialize | 1 |
| 续期 Token | IMusicContentCenter | renewToken | 1 |
| 开启视频与本地预览 | IRtcEngine | enableVideo | 1 |
| 加入频道 | IRtcEngine | joinChannel | 2 |
| 离开频道 | IRtcEngine | leaveChannel | 2 |
| 频道场景 | IRtcEngine | setChannelProfile | 1 |
| 切换角色 | IRtcEngine | setClientRole | 2 |
| 绑定本地画面 | IRtcEngine | setupLocalVideo | 1 |
muteRemoteAudioStream(uid: uid_t, mute: bool): int
initialize(config: const LocalSpatialAudioConfig&): int
renewToken(token: const char*): int
enableVideo(): int
joinChannel(token: const char*, channelId: const char*, info: const char*, uid: uid_t): int
leaveChannel(): int
setChannelProfile(profile: CHANNEL_PROFILE_TYPE): int
setClientRole(role: CLIENT_ROLE_TYPE): int
setupLocalVideo(canvas: const VideoCanvas&): int事件与回调
回调注册在 IRtcEngineEventHandler 上;不同端的命名可能不同,完整清单见同端 API 参考页。
| 回调 | 签名 | 用途 |
|---|---|---|
onConnectionStateChanged | onConnectionStateChanged(state: CONNECTION_STATE_TYPE, reason: CONNECTION_CHANGED_REASON_TYPE): void | 入会结果 / 连接状态变化:据此更新 UI 并决定是否重连。 |
onUserJoined | onUserJoined(uid: uid_t, elapsed: int): void | 远端用户加入:分配画面容器。 |
onFirstRemoteVideoDecoded | onFirstRemoteVideoDecoded(uid: uid_t, width: int, height: int, elapsed: int): void | 远端视频状态:首帧解码后即可渲染。 |
onUserOffline | onUserOffline(uid: uid_t, reason: USER_OFFLINE_REASON_TYPE): void | 远端用户离开:释放容器与订阅。 |
onRequestToken | onRequestToken(): void | Token 即将过期:调用服务端续期后 `renewToken`。 |
onError | onError(err: int, msg: const char*): void | 运行时错误:`err` 为声网错误号,按错误码表分流。 |
onNetworkQuality | onNetworkQuality(uid: uid_t, txQuality: int, rxQuality: int): void | 网络质量:上报到水晶球或提示用户。 |
错误码
| 常量 | 值 |
|---|---|
ERR_ABORTED | 20 |
ERR_ADM_GENERAL_ERROR | 1005 |
ERR_ADM_INIT_PLAYOUT | 1008 |
ERR_ADM_INIT_RECORDING | 1011 |
ERR_ADM_START_PLAYOUT | 1009 |
ERR_ADM_START_RECORDING | 1012 |
ERR_ADM_STOP_PLAYOUT | 1010 |
ERR_ADM_STOP_RECORDING | 1013 |
ERR_ALREADY_IN_USE | 19 |
ERR_BITRATE_LIMIT | 115 |
ERR_BUFFER_TOO_SMALL | 6 |
ERR_CLIENT_IS_BANNED_BY_SERVER | 123 |
ERR_CONNECTION_INTERRUPTED | 111 |
ERR_CONNECTION_LOST | 112 |
ERR_DATASTREAM_DECRYPTION_FAILED | 122 |
ERR_DECRYPTION_FAILED | 120 |
ERR_ENCRYPTED_STREAM_NOT_ALLOWED_PUBLISH | 130 |
ERR_FAILED | 1 |
ERR_INIT_NET_ENGINE | 21 |
ERR_INVALID_APP_ID | 101 |
ERR_INVALID_ARGUMENT | 2 |
ERR_INVALID_CHANNEL_NAME | 102 |
ERR_INVALID_STATE | 8 |
ERR_INVALID_TOKEN | 110 |
ERR_INVALID_USER_ACCOUNT | 134 |
ERR_INVALID_USER_ID | 121 |
ERR_JOIN_CHANNEL_REJECTED | 17 |
ERR_LEAVE_CHANNEL_REJECTED | 18 |
ERR_LOAD_MEDIA_ENGINE | 1001 |
ERR_NOT_INITIALIZED | 7 |
ERR_NOT_IN_CHANNEL | 113 |
ERR_NOT_READY | 3 |
ERR_NOT_SUPPORTED | 4 |
ERR_NO_PERMISSION | 9 |
ERR_NO_SERVER_RESOURCES | 103 |
ERR_OK | 0 |
ERR_REFUSED | 5 |
ERR_RESOURCE_LIMITED | 22 |
ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED | 119 |
ERR_SIZE_TOO_LARGE | 114 |
ERR_STREAM_MESSAGE_TIMEOUT | 117 |
ERR_TIMEDOUT | 10 |
ERR_TOKEN_EXPIRED | 109 |
ERR_TOO_MANY_DATA_STREAMS | 116 |
ERR_VDM_CAMERA_NOT_AUTHORIZED | 1501 |
IRtcEngine | null |
平台 REST 层用 REST 错误码;SDK 层把连接/鉴权失败映射成声网错误号,映射表见 各端 SDK 错误标识。