UOS Hello 游戏语音基础功能接入指南
UOS Hello 游戏语音基础功能接入指南
使用Hello轻松畅享游戏内多人实时语音互动
1. 工作流程与准备工作
本文介绍如何集成Hello服务,通过少量代码从 0 开始实现一个简单的实时互动 App,适用于游戏内置语音通话场景。首先,你需要了解以下有关音频实时互动的基础概念:
- 频道:用于传输数据的通道,在同一个频道内的用户可以进行实时互动。
- 主播:可以在频道内 发布 音视频,同时也可以 订阅 其他主播发布的音视频。
- 观众:可以在频道内 订阅 音视频,不具备发布 音视频权限。

所有用户调用 joinChannel 方法加入频道,并根据需要设置用户角色:
- 指挥模式:如果用户需要在频道中发流,则设为主播;如果用户只需要收流,则设为观众。例如游戏内国战指挥模式,公会会长和核心小队队长是主播角色,其他团队成员是观众负责听从会长和队长指挥则是观众角色即可。
- 小队语音:将所有的用户角色都为主播。例如Moba游戏的4人小队,全员都是主播不存在观众。
- 通过设置小队角色加上用户加入多频道的方法,可以实现游戏内的各种玩法,例如国战语音、小队语音、开黑语音、团本语音等。
加入频道后,不同角色的用户具备不同的行为:
- 所有用户默认都可以接收频道中的音视频流。
- 主播可以在频道内发布音视频流。
- 观众如果需要发流,可在频道内调用 setClientRole 方法修改用户角色,使其具备发流权限。
下图图展示了实现纯语音互动的基本流程.
2.接入 UOS Hello
安装SDK
参考 Launcher 教程,安装 Launcher 后,关联 UOS APP, 开启 Hello 服务并安装 Hello SDK。
注意: 请务必确认在进行后续教程之前,已经成功完成了 Launcher 教程的安装步骤,否则可能导致后续接入无法顺利进行。
导入类 & 初始化SDK
using UnityEngine;
using UnityEngine.UI;
using Unity.UOS.Auth;
using Agora.Rtc;
// 初始化 sdk instance
try
{
HelloSDK.Initialize();
}
catch (HelloClientException e)
{
Debug.Log($"failed to initialize sdk, clientEx: {e.Message}");
throw;
}
catch (HelloServerException e)
{
Debug.Log($"failed to initialize sdk, serverEx: {e.Message}");
throw;
}SDK鉴权
请您在使用 当前服务的SDK 之前,先确认是否需要同步启用我们的 UOS Passport 服务。
启用 UOS Passport 服务,可实现 UOS 系统账号体系打通(即多服务共用同一套 UOS Passport 账号,无需重复授权登录),简化账号管理流程。
特别注意 : UOS Passport 服务为独立计费服务,启用后将根据其专属计费规则额外计费: UOS Passport 计费规则
- 不使用 UOS Passport。 请确保在调用 当前服务的SDK 提供的方法之前 已经完成用户授权:
using Unity.UOS.Auth;
// 用户授权 (每次初始化服务SDK 需进行用户授权)
string userId = <userId>; // 需要授权的 UserId
string userName = <userName>; // 可选, 需要授权的 UserName
await AuthTokenManager.GenerateAccessToken(userId, userName);使用 UOS Passport。 请确保 已开通 UOS Passport 服务 并在调用 当前服务的SDK 提供的方法之前 用户已经完成 Passport 用户登录:
- 方式一:使用「Passport 外部账号系统接入」进行登录
- 方式二:使用「Passport Login」进行登录
初始化 RTC 引擎
var handler = new UserEventHandler(this);
var context = new RtcEngineContext
{
channelProfile = CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING,
audioScenario = AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT,
areaCode = AREA_CODE.AREA_CODE_GLOB
};
// 初始化语音引擎RtcEngine
RtcEngine = await HelloSDK.InitRtcEngine(context, handler);
Debug.Log($"successfully init agora rtc engine");
// 生成声网项目鉴权AccessToken
await GenerateAccessToken(channelName, new HelloOptions { role = Role.Publisher });
Debug.Log($"access token: {TokenInfo.AccessToken}");
// 配置语音引擎
RtcEngine.EnableAudio();
RtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
private async Task GenerateAccessToken(string channel, HelloOptions options = null)
{
try
{
TokenInfo = await HelloSDK.Instance.GenerateAccessToken(channel, options);
}
catch (HelloClientException e)
{
Debug.LogErrorFormat("failed to generate token, clientEx: {0}", e.Message);
throw;
}
catch (HelloServerException e)
{
Debug.LogErrorFormat("failed to generate token, serverEx: {0}", e.Message);
throw;
}
}
public class TokenInfo {
public string ChannelName;
public string Role;
public string UserId;
public string PersonaId;
public string AccessToken;
}加入频道
// 加入频道
public void JoinChannel()
{
// TokenInfo来自 await GenerateAccessToken(channelName, new HelloOptions { role = Role.Publisher });
RtcEngine.JoinChannelWithUserAccount(TokenInfo.AccessToken, TokenInfo.ChannelName, TokenInfo.UserId);
}更多频道相关使用方法参考 频道相关API。
开始音频互动
在开始音频互动前,先检查是否已获取设备权限。
- 检查是否已获取设备权限。调用 RequestMicrophonePermission 方法检查是否已获取实现语音互动所需的权限(参见 「处理权限请求」)。
void Update() {
RequestMicrophonePermission();
}- 开始语音测试
public void StartEchoTest()
{
Debug.Log($"echo channelName {channelName} access token {TokenInfo.AccessToken}");
var config = new EchoTestConfiguration
{
intervalInSeconds = 2,
enableAudio = true,
enableVideo = false,
token = TokenInfo.AccessToken,
channelId = TokenInfo.ChannelName
};
RtcEngine.StartEchoTest(config);
Log.UpdateLog("StartEchoTest, speak now. You cannot conduct another echo test or join a channel before StopEchoTest");
}离开频道
public void LeaveChannel()
{
// 离开频道
RtcEngine.LeaveChannel();
}}常用的回调
// 创建用户回调类实例,并设置回调
private void InitEventHandler() {
UserEventHandler handler = new UserEventHandler(this);
RtcEngine.InitEventHandler(handler);
}
// 实现你自己的回调类,可以继承 UOSRtcEngineEventHandler 接口类实现
internal class UserEventHandler : UOSRtcEngineEventHandler
{
private readonly HelloSample _audioSample;
internal UserEventHandler(HelloSample audioSample)
{
_audioSample = audioSample;
}
public override void OnError(int err, string msg)
{
_audioSample.Log.UpdateLog($"OnError err: {err}, msg: {msg}");;
}
public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
{
base.OnJoinChannelSuccess(connection, elapsed);
int build = 0;
_audioSample.Log.UpdateLog($"sdk version: ${_audioSample.RtcEngine.GetVersion(ref build)}");
_audioSample.Log.UpdateLog(
$"OnJoinChannelSuccess channelName: {connection.channelId}, uid: {connection.localUid}, elapsed: {elapsed}");
}
public override void OnRejoinChannelSuccess(RtcConnection connection, int elapsed)
{
_audioSample.Log.UpdateLog("OnRejoinChannelSuccess");
}
public override void OnLeaveChannel(RtcConnection connection, RtcStats stats)
{
base.OnLeaveChannel(connection, stats);
_audioSample.Log.UpdateLog("OnLeaveChannel");
}
public override void OnClientRoleChanged(RtcConnection connection, CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole, ClientRoleOptions newRoleOptions)
{
_audioSample.Log.UpdateLog("OnClientRoleChanged");
}
public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
{
_audioSample.Log.UpdateLog($"OnUserJoined uid: ${uid} elapsed: ${elapsed}");
}
public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
{
_audioSample.Log.UpdateLog($"OnUserOffLine uid: ${uid}, reason: ${(int)reason}");
}
}处理权限请求
本小节介绍如何获取设备的摄像头、麦克风等权限。在 Unity 2018.3 或以上版本中,Unity 不会主动向用户获取麦克风和相机权限,因此你需要请求获取权限。
如果你开发的目标平台是 Android,Unity 提供了权限请求的 API CheckPermission。你可以调用该方法来获取相关权限。参考下列步骤来获取安卓权限:
- 导入 Unity 的 Android 命名空间。
#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
using UnityEngine.Android;
#endif- 创建需要获取的权限列表,包括摄像头和麦克风。
#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
private ArrayList permissionList = new ArrayList() { Permission.Camera, Permission.Microphone };
#endif- 检查是否已获取权限。
private void CheckPermissions() {
#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
foreach (string permission in permissionList) {
if (!Permission.HasUserAuthorizedPermission(permission)) {
Permission.RequestUserPermission(permission);
}
}
#endif
}如果你开发的目标平台是 iOS 或 macOS,声网 RTC Unity SDK 在 Editor 文件夹下提供一个构建后处理脚本 BL_BuildPostProcess.cs。在你将项目从 Unity Editor 中构建并导出为 iOS 项目后,该脚本会自动向 Info.plist 文件添加摄像头和麦克风权限,无需你手动处理。
Windows 系统会在应用程序首次尝试使用摄像头或麦克风等功能时,自动向用户弹出权限请求提示,因此你无需额外处理权限请求。
3. 示例项目
UOS Hello提供了开源示例项目供你参考,你可以前往下载或查看其中的源代码。