为方便开发者调试和接入腾讯云游戏多媒体引擎产品 API,本文向您介绍游戏多媒体引擎 3D 音效的接入技术。
使用场景
在普通的进房实时语音中,玩家的声音不具有 3D 音效的效果,玩家之间只能进行很简单的互动;而引入 3D 位置语音之后,玩家在喊话过程中会暴露自己的方位和位置信息,玩家的声音也会根据位置变化而实时改变。可以说,3D 音效让《大逃杀》这种玩家间的沟通和战斗体验更真实,感受更加沉浸式、更加身临其境的吃鸡玩法。
前提条件
已开通实时语音服务:可参见 语音服务开通指引。
已接入 GME SDK:包括核心接口和实时语音接口的接入,详情可参见 Native SDK 快速接入、Unity SDK 快速接入、Unreal SDK 快速接入。
实现流程
实现流程图
下图为 3D 音效实现的流程图,其中蓝色部分为对比普通进房实时语音需要接入的步骤。
?
?
?初始化 3D 音效引擎
此函数用于初始化 3D 音效引擎,在进房后调用。在使用 3D 音效之前必须先调用此接口,只接收 3D 音效而不发出 3D 音效的用户也需要调用此接口。
函数原型
public abstract int InitSpatializer(string modelPath)
参数 | 类型 | 意义 |
modelPath | string | 3D 音效资源文件的绝对路径 |
参数中的 3D 音效资源文件,需要另外下载到本地,根据接入 SDK 的版本进行区分:
如果是v2.8以下版本,请单击 下载,md5: d0b76aa64c46598788c2f35f5a8a8694。
如果是v2.8-v2.9.5版本,请单击 下载,md5: 3d4d04b3949e267e34ca809e8a0b9243。
如果是v2.9.6及以上版本,由于3D音效资源文件已内置,此处 modelPath 可填空。
关于资源路径
以 Unity 为例,建议将 3D 文件放在项目的 StreamingAssets 目录下,并参考 SampleCode 中 copyFileFromAssetsToPersistent 函数写法,将资源文件拷贝到不同平台的相应目录中。
以 Unreal 为例,参考 SampleCode 中 CopyAllAssetsToExternal 函数写法,将 3D 模型文件拷贝后再读取路径。
开启或关闭 3D 音效
此函数用于开启或关闭 3D 音效。开启之后可以听到 3D 音效。
函数原型
public abstract int EnableSpatializer(bool enable, bool applyToTeam)
参数 | 类型 | 意义 |
enable | bool | 开启之后可以听到 3D 音效 |
applyToTeam | bool | 3D 语音是否作用于小队内部,仅 enable 为 true 时有效 |
获取当前 3D 音效状态
此函数用于获取当前 3D 音效状态。
函数原型
public abstract bool IsEnableSpatializer()
返回值 | 意义 |
true | 开启状态 |
false | 关闭状态 |
设置 3D 音效衰减距离
需要设置衰减距离,建议设置为 100。
距离与声音衰减的关系
3D 音效中,音源音量的大小与音源距离有一定的衰减关系。单位距离超过 range 之后,音量衰减到几乎为零。
距离范围(引擎单位) | 衰减公式 |
0 < N < range/10 | 衰减系数:1.0 (音量无衰减) |
N ≥ range/10 | 衰减系数:range/10/N |
?
?
?函数原型
public abstract void UpdateAudioRecvRange(int range)
参数 | 类型 | 意义 |
range | int | 设定音效可接收的范围,建议设置100,此处的距离单位为游戏引擎中的距离单位 |
更新声源方位(包含朝向)
此函数用于更新声源方位角信息,每帧调用便可实现 3D 音效效果。
函数原型
public abstract int UpdateSelfPosition(int position[3], float axisForward[3], float axisRight[3], float axisUp[3])
参数 | 类型 | 意义 |
position | int[] | 自身在世界坐标系中的坐标,顺序是前、右、上 |
axisForward | float[] | 自身坐标系前轴的单位向量 |
axisRight | float[] | 自身坐标系右轴的单位向量 |
axisUp | float[] | 自身坐标系上轴的单位向量 |
示例代码
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);
本地方位接口(VR 场景)
本接口适用于 VR 设备中,对 3D 位置变化有极高要求的场景。此功能为高级接口,需要在 GME 2.9.2 以上版本才可使用。
在一般 3D 的场景中,用户只需要通过函数 UpdateSelfPosition 更新自己的位置信息,然后经网络发送给其他用户。UpdateOtherPosition支持本地传入其他玩家的位置信息,不经过网络发送,适用于 VR 游戏场景。
为了避免和远程更新的坐标发生冲突,只要您调用了UpdateOtherPosition,远程坐标便会被丢弃,这种影响持续到再一次进房。所以,您如果要通过本地方式更新玩家坐标,请更新所有玩家的坐标。
函数原型
public abstract int UpdateOtherPosition(string openID, int position[3])
参数 | 类型 | 意义 |
openID | string | 用户标识。 |
position | int[] | 其他玩家在世界坐标系中的坐标,顺序是前、右、上 |
注意
您如果要通过本地方式更新玩家坐标,请遍历所有的玩家坐标,通过此接口将坐标进行传入。
3D 语音黑名单接口
注意
此接口在 GME 2.9.3 及以上版本 SDK 生效。
目前 3D 音效调用后对房间内所有人都会生效。由于某些特定场景下,不希望接受到的某个人声音会有因 3D 音效而产生的衰减,可以通过调用此接口,将某个人加入 3D 语音黑名单中,加入后此 openid 的声音不再有 3D 音效效果。
virtual int AddSpatializerBlacklist(const char* openId);
如果需要将此 openid 从黑名单中移除,需要调用以下接口:
virtual int RemoveSpatializerBlacklist(const char* openId);
如果需要清空黑名单,需要调用以下接口:
virtual int ClearSpatializerBlacklist();
问题排查
如果接入后测试语音,没有 3D 音效效果,排查路径如下:
1. 确定是否已经进房成功及开启麦克风?双方能否听到声音?
2. 是否适用双声道耳机进行收听?
3. InitSpatializer 接口返回值是否为0?
4. UpdateAudioRecvRange 设置是否过小?
5. 是否有周期性的调用 UpdateSelfPosition 接口?
6. 通过 错误码文档 进行判断并解决。