二、应用场景
| 大逃杀游戏 | 提供大逃杀类型游戏、生存射击类手游中特有的“仅小队”或“所有人”的语音模式。在游戏设置中,根据玩家选择: 1. 如果使用“仅小队”模式,则只能听见同队伍中队友说话的声音。 2. 如果使用“所有人”模式,则可以听见队伍中队友声音,以及一定范围内其他对局玩家说话的声音。 |
| 沉浸式虚拟场景 | 例如游戏演唱会等虚拟场景中,可以通过范围语音实现演唱者在虚拟房间内唱歌,台下所有听众可以听到歌声的同时,能与自身一定范围内其他听众进行交流,最高可支持同房间内上万人同时开启麦克风。 |
三、体验效果
可以到 Demo 体验 中下载体验程序,体验 3D 音效及范围语音的效果。
四、基本概念
使用范围语音功能,涉及到语音模式、语音接收范围以及 TeamID 这三个概念。
五、语音模式
当进入范围语音房间时,有两种语音模式可供选择:
| 语音模式 | 参数名称 | 功能 |
| 所有人 | RANGE_AUDIO_MODE_WORLD | 设置后玩家附近一定范围的人都能听到该玩家讲话,如果范围内也有玩家设置为此模式,则也可以互相通话。队友可以互相听到 |
| 仅小队 | RANGE_AUDIO_MODE_TEAM | 仅队友可以互相听到 |
注意:队友之间的通话不受距离以及语音模式的影响。
六、语音接收范围
如果设置的语音模式为**所有人(RANGE_AUDIO_MODE_WORLD)**,此时的语音接收范围受 UpdateAudioRecvRange 接口影响。
假设以下两个玩家 A 与 B 为不同的小队,且设置的语音模式为所有人(RANGE_AUDIO_MODE_WORLD):
| 玩家坐标 | 语音接收范围 | 与另一玩家声音可达情况 | 与队友声音可达情况 |
| A(0,0,0) | 10米 | 可以听到玩家 B 的声音,因为 B 玩家距离 A 玩家在10米内 | 不影响同一小队成员互相通话 |
| B(0,8,0) | 5米 | 不可以听到玩家 A 的声音,因为 A 玩家与 B 玩家距离超过5米 | 不影响同一小队成员互相通话 |
注意:说明:
注意:具体玩家声音可达情况请参见 附录。
七、TeamID
使用范围语音,需要调用 SetRangeAudioTeamID 接口设置小队号 TeamID,再调用 EnterRoom 接口进入语音房间。
·当进入语音房间时指定的 TeamID != 0 时,进入范围语音房间模式。如果某成员使用 TeamID = 1 进入语音房间,当他设置语音模式为 RANGE_AUDIO_MODE_TEAM,则只有 TeamID = 1 的成员能听到他的声音;如果他设置的语音模式为 RANGE_AUDIO_MODE_WORLD,则除了 TeamID = 1 的成员,一定范围内的玩家也能听到他的声音。
| TeamID 情况 | 语音模式 | 范围 | 声音可达情况 |
| TeamID != 0,假设 TeamID = 1 | RANGE_AUDIO_MODE_TEAM | 10米 | 声音只能和 TeamID = 1 的成员互通 |
| | RANGE_AUDIO_MODE_WORLD | 10米 | 声音能和 TeamID = 1 的成员、以及语音模式设置为 RANGE_AUDIO_MODE_WORLD 的同房间10米范围内成员互通 |
·如果某成员使用 TeamID = 0 进入语音房间,则为范围语音主持人模式,房间内所有人(不论语音模式是所有人还是仅小队)都可以听到该成员的声音。
| TeamID 情况 | TeamID 修改时机 | 范围 | 声音可达情况 |
| TeamID = 0 | 进房前 TeamID != 0,进房后修改 TeamID = 0 | 10米 | 说话声音全房间成员(不论语音模式是所有人还是仅小队)都能听到能与 TeamID = 0 的成员互相沟通能听到设置为 RANGE_AUDIO_MODE_WORLD 的同房间10米范围内成员声音 |
| | 进房前 TeamID = 0,以 TeamID = 0 进入房间 | 10米 | 说话声音全房间成员(不论语音模式是所有人还是仅小队)都能听到能与 TeamID = 0 的成员互相沟通不能听到房间内其他人说话声音 |
八、示例场景
·大逃杀游戏:例如一个大逃杀类型的游戏,每4个人为一个队伍,则这4个人需要设置一个小队号 TeamID,每100人为一个对局房间,一个对局共25个小队,则25个小队都进去一个语音房间。在对局中,如果某玩家想和10米范围内的陌生人沟通,则将语音距离范围设置为10,将语音模式设置为 RANGE_AUDIO_MODE_WORLD,同时打开麦克风及扬声器。如果他只想和小队成员沟通,不和非小队的成员沟通,则只需要将语音模式设置为 RANGE_AUDIO_MODE_TEAM。
·游戏演唱会:在游戏中如果需要举办演唱会,歌手不需要和游戏玩家有互动,可以让游戏玩家通过 TeamID = OpenID 进入范围语音房间,设置语音模式为 RANGE_AUDIO_MODE_WORLD,依照游戏玩法设置语音距离范围,这样游戏玩家可以和附近玩家沟通交流;歌手将 TeamID 设置为 0 后进入房间,歌手的声音整个房间的人都能听见,但歌手听不见其他人的声音。
·主持人模式:在游戏中例如虚拟桌游场景,主持人说话声音即要房间内所有人听见,也要听见范围内玩家说话的声音,可以让主持人先以 TeamID != 0 的形式进入房间,进房后将 TeamID 设置为 0,此时主持人说话全房间的人都能听见,主持人也能听见范围内玩家说话的声音。
九、前提条件
·已开通实时语音服务:可参见 语音服务开通指引。
·已接入GME SDK:包括核心接口和实时语音接口的接入,详情可参见 Native SDK 快速接入、Unity SDK 快速接入、Unreal SDK 快速接入。
·万人范围语音:如果同房间内使用范围语音人数超过1千人,请 提交工单 联系 GME 开发者。
十一、1. 设置 TeamID
·进房前,通过此接口设置队伍号,影响下一次进房。
·进房后,可通过此接口修改队伍号,设置后立即生效。
·退房后,TeamID 不会自动重置为0,所以一旦决定调用此语音模式,请在每次 EnterRoom 之前都调用此方法设置 TeamID。
·退房后再进房,请在退房成功回调回来之后再调用设置队伍号接口。
十二、函数原型
ITMGContext SetRangeAudioTeamID(int teamID)
| 参数 | 类型 | 意义 |
| teamID | int | 队伍号,专供范围语音模式中使用。当 TeamID 为0时,通话模式为普通小队语音,默认0。 |
十三、2. 设置语音模式
·进房前,通过调用此接口修改语音模式,影响下一次进房。
·进房后,通过调用此接口修改语音模式,将直接改变当前用户的语音模式。
·退房后,此参数不会自动重置为 MODE_WORLD,所以一旦决定调用此方法,请在每次 EnterRoom 之前都调用此方法设置语音模式。
十四、函数原型
ITMGRoom int SetRangeAudioMode(RANGE_AUDIO_MODE rangeAudioMode)
| 参数 | 类型 | 意义 |
| rangeAudioMode | int | 0(MODE_WORLD) 代表“所有人”,1(MODE_TEAM) 代表"仅小队" |
十五、3. 进入语音房间
在调用 EnterRoom 之前,需调用以下两个 API:SetRangeAudioTeamID、 SetRangeAudioMode。
十六、函数原型
ITMGContext.GetInstance(this).EnterRoom(roomId,ITMG_ROOM_TYPE_FLUENCY, authBuffer);
进入语音房间后,随后监听进房的回调并进行处理。
public void OnEvent(ITMGContext.ITMG_MAIN_EVENT_TYPE type, Intent data) { if (ITMGContext.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_ENTER_ROOM == type) { //对事件返回的 Data 进行解析 int nErrCode = data.getIntExtra("result" , -1); String strErrMsg = data.getStringExtra("error_info"); if (nErrCode == AVError.AV_OK) { //收到进房信令,进房成功,可以操作设备 ScrollView_ShowLog("EnterRoom success"); Log.i(TAG,"EnterRoom success!"); } else { //进房失败,需分析返回的错误信息 ScrollView_ShowLog("EnterRoom fail :" + strErrMsg); Log.i(TAG,"EnterRoom fail!"); } } }
在进房成功后,调用 UpdateAudioRecvRange(至少调用一次),及每帧调用 UpdateSelfPosition。
十七、4. 设置接收语音距离范围
·通过此方法用于设置接收的语音范围(距离以游戏引擎为准),只支持在进房成功后调用。
·此方法必须配合 UpdateSelfPosition 更新声源方位联合使用。
·此方法只需调用一次即可生效,支持修改。
十八、函数原型
ITMGRoom int UpdateAudioRecvRange(int range)
| 参数 | 类型 | 意义 |
| range | int | 最大可以接收音频的范围,单位为引擎距离单位 |
十九、示例代码
ITMGContext.GetInstance().GetRoom().UpdateAudioRecvRange(300);
20、5. 更新声源方位
更新声源方位,目的是告诉服务器本端位置,通过本端世界坐标+本端接收音频的范围,与其他端世界坐标+其他端接收音频的范围进行判断,达到范围语音效果。
·此函数用于更新声源位置信息,只支持在进房成功后调用,且需要每帧调用,以 Unity 引擎为例,此接口需要在 Update 中调用。
·使用范围语音一定要更新声源方位,如果不需要范围判断能力,也需要进房后调用此接口一次。
·如果需要同时使用 3D 音效效果,此接口中的参数 axisForward、axisRight 及 axisUp 需要按照下文范围语音结合 3D 音效进行设置。
21、函数原型
public abstract int UpdateSelfPosition(int position[3], float axisForward[3], float axisRight[3], float axisUp[3])
| 参数 | 类型 | 意义 |
| position | int[] | 自身在世界坐标系中的坐标,顺序是前、右、上 |
| axisForward | float[] | 在本产品中无需关注 |
| axisRight | float[] | 在本产品中无需关注 |
| axisUp | float[] | 在本产品中无需关注 |
22、范围语音结合 3D 音效
上文所介绍的范围语音功能,即通过距离来进行控制声音的可达性,如果需要更加沉浸式的体验,建议配合 3D 音效一起使用。
23、使用流程
使用范围语音的同时,如果需要同时使用 3D 音效功能,需要以下几个步骤,在进房后使用范围语音步骤1、2、3完成后,初始化 3D 引擎以及打开3D音效。
注意:说明:
注意:流程图中绿色部分为3D语音所需流程。
24、前提条件
参考 范围语音使用流程,完成步骤1、2、3。
25、1. 初始化 3D 音效引擎
此函数用于初始化 3D 音效引擎,在进房后调用。在使用 3D 音效之前必须先调用此接口,只接收 3D 音效而不发出 3D 音效的用户也需要调用此接口。
26、函数原型
public abstract int InitSpatializer(string modelPath)
| 参数 | 类型 | 意义 |
| modelPath | string | 填空即可 |
27、2. 开启或关闭 3D 音效
此函数用于开启或关闭 3D 音效。开启之后可以听到 3D 音效。
28、函数原型
public abstract int EnableSpatializer(bool enable, bool applyToTeam)
| 参数 | 类型 | 意义 |
| enable | bool | 开启之后可以听到 3D 音效 |
| applyToTeam | bool | 3D 语音是否作用于小队内部,仅 enable 为 true 时有效 |
通过 IsEnableSpatializer 接口获取 3D 音效状态。
29、3. 设置接收语音距离范围(3D)
·通过此方法用于设置接收的语音范围(距离以游戏引擎为准),只支持在进房成功后调用。
·此方法必须配合 UpdateSelfPosition 更新声源方位联合使用。
·此方法只需调用一次即可生效。
·3D 音效中,音源音量的大小与音源距离有一定的衰减关系。单位距离超过 range 之后,音量衰减到几乎为零。
·距离与声音衰减的关系参考文档附录。
30、函数原型
ITMGRoom int UpdateAudioRecvRange(int range)
| 参数 | 类型 | 意义 |
| range | int | 最大可以接收音频的范围,单位为引擎距离单位 |
31、示例代码
ITMGContext.GetInstance().GetRoom().UpdateAudioRecvRange(300);
32、4. 更新声源方位(3D)
更新声源方位,目的是告诉服务器本端位置,通过本端世界坐标+本端接收音频的范围,与其他端世界坐标+其他端接收音频的范围进行判断,达到范围语音效果。
·此函数用于更新声源位置信息,只支持在进房成功后调用,且需要每帧调用,以 Unity 引擎为例,此接口需要在 Update 中调用。
·请直接复制并调用示例代码使用此功能。
33、函数原型
public abstract int UpdateSelfPosition(int position[3], float axisForward[3], float axisRight[3], float axisUp[3])
| 参数 | 类型 | 意义 |
| position | int[] | 自身在世界坐标系中的坐标,顺序是前、右、上 |
| axisForward | float[] | 自身坐标系前轴的单位向量 |
| axisRight | float[] | 自身坐标系右轴的单位向量 |
| axisUp | float[] | 自身坐标系上轴的单位向量 |
34、示例代码
Unreal
FVector cameraLocation = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraLocation();FRotator cameraRotation = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraRotation();int position[] = { (int)cameraLocation.X, (int)cameraLocation.Y, (int)cameraLocation.Z };FMatrix matrix = ((FRotationMatrix)cameraRotation);float forward[] = { matrix.GetColumn(0).X, matrix.GetColumn(1).X, matrix.GetColumn(2).X };float right[] = { matrix.GetColumn(0).Y, matrix.GetColumn(1).Y, matrix.GetColumn(2).Y };float up[] = { matrix.GetColumn(0).Z, matrix.GetColumn(1).Z, matrix.GetColumn(2).Z};ITMGContextGetInstance()->GetRoom()->UpdateSelfPosition(position, forward, right, up);
Unity
Transform selftrans = currentPlayer.gameObject.transform;Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, selftrans.rotation, Vector3.one);int[] position = new int[3] { selftrans.position.z, selftrans.position.x, selftrans.position.y};float[] axisForward = new float[3] { matrix.m22, matrix.m02, matrix.m12 };float[] axisRight = new float[3] { matrix.m20, matrix.m00, matrix.m10 };float[] axisUp = new float[3] { matrix.m21, matrix.m01, matrix.m11 };ITMGContext.GetInstance().GetRoom().UpdateSelfPosition(position, axisForward, axisRight, axisUp);
35、对主持人禁止使用 3D 音效
如果场景中有玩家使用范围语音主持人模式,即他的声音需要全房间玩家都能收听到,需要参考 3D 语音黑名单接口,在所有收听端将主持人加入到收听端的 3D 语音黑名单中,避免出现 3D 语音功能衰减效果对主持人声音可达性的影响。
不同角色的 API 调用时序如下:
| 主持人 API 时序 | 听众 API 时序 |
| | |
37、不同语音模式
不同语音模式下,玩家声音可达情况:
·假设 A 玩家状态为“所有人”,对应 B 玩家在不同语音模式下声音可达情况:
| 是否同一小队 | 是否范围内 | 语音模式 | A与B 是否能相互听到对方的声音 |
| 同一小队 | 是 | MODE_WORLD | 是 |
| | | MODE_TEAM | 是 |
| | 否 | MODE_WORLD | 是 |
| | | MODE_TEAM | 是 |
| 不同小队 | 是 | MODE_WORLD | 是 |
| | | MODE_TEAM | 否 |
| | 否 | MODE_WORLD | 否 |
| | | MODE_TEAM | 否 |
·假设 A 玩家状态为“仅小队”,对应 B 玩家在不同语音模式下声音可达情况:
| 是否同一小队 | 是否范围内 | 语音状态 | A与B 是否能相互听到对方的声音 |
| 同一小队 | 是 | MODE_WORLD | 是 |
| | | MODE_TEAM | 是 |
| | 否 | MODE_WORLD | 是 |
| | | MODE_TEAM | 是 |
| 不同小队 | 是 | MODE_WORLD | 否 |
| | | MODE_TEAM | 否 |
| | 否 | MODE_WORLD | 否 |
| | | MODE_TEAM | 否 |
38、距离与声音衰减的关系
3D 音效中,音源音量的大小与音源距离有一定的衰减关系。单位距离超过 range 之后,音量衰减到几乎为零。
| 距离范围(引擎单位) | 衰减公式 |
| 0 < N < range/10 | 衰减系数:1.0 (音量无衰减) |
| N ≥ range/10 | 衰减系数:range/10/N |