二、环境要求
·Unity 2018.4.3f1 及以上版本。
·Windows 平台设备。
·能运行 Unity 工程的配置环境。
三、前提条件
请提前申请开通 GME 实时语音、语音消息服务,获取到 AppId 以及 Key。申请 GME 服务,详情请参见 服务开通,appId 对应控制台的 AppID,authKey 对应控制台的权限密钥。
五、步骤1:下载工程
通过 下载指引 下载 Unity Sample Project,下载后请将文件进行解压。
六、步骤2:导入工程
在 Unity Hub 中点击【Open】按钮,导入步骤1中下载并解压过的工程,请注意导入工程的方式根据不同的 Unity Hub 版本会有所不同。
七、步骤3:修改配置
导入工程后,通过 Unity Hub 打开此工程。打开过程中会进行编译,请耐心等待一段时间。工程打开后会在 Console 窗口中显示报错信息:
此处报错信息为引导作用,具体修改方法如下参考操作 :
在 Project 窗口中, 通过路径 Assets/Scripts/Demo 找到代码文件 UserConfig.cs,打开此文件后,将如下代码中的 appID 及 appKey 修改为所申请的 GME 控制台 服务管理-应用设置 中的 AppID 以及权限密钥。
public static string GetAppID() { return PlayerPrefs.GetString("AppID", AppID To Replace Here https://www.tencentcloud.com/document/product/607/10782);}public static string GetAuthKey(){ return PlayerPrefs.GetString("AuthKey", AppKey To Replace Here https://www.tencentcloud.com/document/product/607/10782);}
此处如果是使用 macOS 平台 Unity 引擎进行开发,某些 Unity 版本下需要将路径 Assets/Editor 路径下的 add_dylib.cs 文件以及 iosProjectScript.cs 文件删除,才可以编译通过,并且需要参考 接入指引 文档对 SDK 文件进行配置,才可以顺利运行工程。
八、步骤4:编译运行
工程游戏场景存放在路径 Assets/Scene/ExperientialDemo 中,其中 ExHomeScene 为启动的第一个 Scene,请双击切换到此游戏场景。
九、运行程序
单击编辑器运行按钮,进入运行程序。
十、步骤1:初始化
UserID:相当于 openID,openID 是应用内用户的唯一标识符,每个端的 openid 必须唯一。
Login:单击 Login,进行初始化
单击 Login 后,会出现 2 个新按钮,单击 Voice Chat 进入实时语音房间配置界面。
Voice Chat:实时语音功能界面。
Voice Message:语音消息功能界面。
此界面的代码在 ExHomeViewController.cs 文件中。
十一、步骤2:实时语音房间配置
·RoomId:房间号码,同房间的人可以互相语音交流。
·RoomType:请使用 Fluency 进入房间。
·JoinRoom:进入语音房间。
配置好实时语音房间号后,单击 JoinRoom 进入实时语音房间。
此界面代码在 ExEnterRoomViewController.cs 文件中。
十二、步骤3:实时语音功能体验
界面上会显示进房的 RoomID 以及本端的 openID。
·RoomID:实时语音房间 ID。
·Self Id:本端 openID。
·Talking Members:房间内正在说话的成员,界面将会显示正在说话的成员 ID。
·Mic:麦克风,勾选表示打开。
·Speaker:扬声器,勾选表示打开。
·3D Voice Effect:3D 音效,勾选表示打开,需要同房间的用户同时打开麦克风、扬声器以及 3D Voice Effec 才可体验,通过设置以下参数进行效果配置:
·Range:设置语音接收范围,单位为游戏引擎单位。
·X:自身 X 轴。
·Y:自身 Y 轴。
·Z:自身 Z 轴。
·XR:绕 X 坐标轴旋转的方向。
·YR:绕 Y 坐标轴旋转的方向。
·ZR:绕 Z 坐标轴旋转的方向。
·Voice Change:实时语音音效,可通过选择不同的参数类型,改变播放音效特性,详情可参考 实时语音音效。
·QuitRoom:退出实时语音房间,回到上一界面。
此界面代码在 ExRoomViewController.cs 文件中。
十三、步骤4:语音消息功能
在 ExHomeScene 界面中,点击 Login 之后,单击 Voice Message 进入语言消息界面:
Language:选择所录制的语言,录制后将转换为对应语言的文本,显示在 Audio-to-Text 一栏中。
Push To Talk:长按 Push To Talk,开始录制;松开 Push To Talk,结束录制。
Audio:录制的语音消息和语音时长。单击 按钮播放录音,播放过程中再次单击,结束播放。
Audio-to-Text:语音转换成的文字。
此界面代码在 ExPttViewController.cs 文件中。
十四、Sample Project 代码介绍
使用 GME 实时语音主要的流程是 Init > EnterRoom > EnableMic > EnableSpeaker。
十五、初始化相关
初始化相关的代码在 ExHomeViewController.cs 文件中的 OnClickLogin 方法中。这里面包含了初始化、语音消息的鉴权初始化、启动周期性调用 Poll 接口功能。
void OnClickLogin(){ string userId = transform.Find ("userId").GetComponent<InputField> ().text; if (userId.Equals ("")) { ShowWarnning("user is empty."); return; } EnginePollHelper.CreateEnginePollHelper(); int ret = ITMGContext.GetInstance().Init(UserConfig.GetExperientialAppID(), userId); if (ret != QAVError.OK){ ShowWarnning(string.Format("Init Failed {0}", ret)); return; } UserConfig.SetUserID(transform.Find("userId").GetComponent<InputField>().text); byte[] sig = UserConfig.GetAuthBuffer(UserConfig.GetExperientialAppID(), "0", userId,UserConfig.GetExperientialauthkey()); if (sig != null){ ITMGContext.GetInstance().GetPttCtrl().ApplyPTTAuthbuffer(sig); ShowWarnning("ApplyPTTAuthbuffer success");} else{ ShowWarnning("get ptt token failed.");} transform.Find("luanchPanel").gameObject.SetActive(true);}
使用 GME 需要周期性的调用 Poll 接口。上面代码中调用了 EnginePollHelper.CreateEnginePollHelper 方法,该方法在 EnginePollHelper.cs 文件中。
十六、进房相关
进房相关的代码在 ExEnterRoomViewController.cs 文件中的 OnClickJoinRoomBtn 方法中。
void OnClickJoinRoomBtn(){ string sRoomId = transform.Find("outroomPanel/roomIDInputField").GetComponent<InputField> ().text; string roomtyepString = roomTypeDropdown.options[roomTypeDropdown.value].text; ITMGRoomType roomtype = _RoomtypeDic [roomtyepString]; showLoadingView(true, "JoiningRoom…"); byte[] authBuffer = UserConfig.GetAuthBuffer(UserConfig.GetExperientialAppID(), UserConfig.GetUserID(), sRoomId,UserConfig.GetExperientialauthkey()); ITMGContext.GetInstance().EnterRoom(sRoomId, roomtype, authBuffer); UserConfig.SetRoomID(sRoomId); UserConfig.SetRoomType(roomtype);}
进房回调监听代码如下:
ITMGContext.GetInstance().OnEnterRoomCompleteEvent += new QAVEnterRoomComplete(OnEnterRoomComplete);
进房回调在同一脚本中的 OnEnterRoomComplete 方法中。
void OnEnterRoomComplete(int err, string errInfo){ showLoadingView (false, ""); if (err != 0) { ShowWarnning (string.Format ("join room failed, err:{0}, errInfo:{1}", err, errInfo)); return; } else{ UnityEngine.Application.LoadLevel("ExRoomScene"); }}
十七、打开设备
进房成功后打开设备,相关代码在 ExRoomViewController.cs 中按钮相关的 Toggle 事件。
void onMicToggle(bool value){ ITMGContext.GetInstance().GetAudioCtrl().EnableMic(value);}void onSpeakerToggle(bool value){ ITMGContext.GetInstance().GetAudioCtrl().EnableSpeaker(value);}
十八、3D 音效相关
3D 音效的接入可以参考 3D 音效文档。在工程中,首先初始化 3D 音效功能,相关代码在 ExRoomViewController.cs 代码文件的 OnVoice3DToggle 方法中。
public void OnVoice3DToggle(bool value){ if (value){ ITMGContext.GetInstance().GetAudioCtrl().InitSpatializer(null); } ITMGContext.GetInstance().GetAudioCtrl().EnableSpatializer(value, false); transform.Find("inroomPanel/3DVoicePanel").gameObject.SetActive(value); updateSpatializer();}
通过 updateSpatializer 接口更新自身位置坐标及朝向信息。
public void updateSpatializer(){ string strRange = transform.Find("inroomPanel/3DVoicePanel/InputFieldRange").GetComponent<InputField>().text; int range = 0; if (Int32.TryParse(strRange, out range)){ ITMGContext.GetInstance().GetRoom().UpdateAudioRecvRange(range);} int x = (int)transform.Find("inroomPanel/3DVoicePanel/SliderX").GetComponent<Slider>().value; int y = (int)transform.Find("inroomPanel/3DVoicePanel/SliderY").GetComponent<Slider>().value; int z = (int)transform.Find("inroomPanel/3DVoicePanel/SliderZ").GetComponent<Slider>().value; float xRotate = transform.Find("inroomPanel/3DVoicePanel/SliderXRotate").GetComponent<Slider>().value; float yRotate = transform.Find("inroomPanel/3DVoicePanel/SliderYRotate").GetComponent<Slider>().value; float zRotate = transform.Find("inroomPanel/3DVoicePanel/SliderZRotate").GetComponent<Slider>().value; transform.Find("inroomPanel/3DVoicePanel/TextXShow").GetComponent<Text>().text = string.Format("{0}", x); transform.Find("inroomPanel/3DVoicePanel/TextYShow").GetComponent<Text>().text = string.Format("{0}", y); transform.Find("inroomPanel/3DVoicePanel/TextZShow").GetComponent<Text>().text = string.Format("{0}", z); transform.Find("inroomPanel/3DVoicePanel/TextPitchShow").GetComponent<Text>().text = string.Format("{0}", (int)xRotate); transform.Find("inroomPanel/3DVoicePanel/TextYawShow").GetComponent<Text>().text = string.Format("{0}", (int)yRotate); transform.Find("inroomPanel/3DVoicePanel/TextRollShow").GetComponent<Text>().text = string.Format("{0}", (int)zRotate); Quaternion rotation = Quaternion.Euler((float)xRotate, (float)yRotate, (float)zRotate); Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, rotation, Vector3.one); int[] position = new int[3] { z, x, 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);}
20、Unity 2022及以上版本编译
使用Unity 2022及以上版本编译GME Demo时会出现以下报错:Assets\\Scripts\\Demo\\AudioListModel.cs(6,19): error CS0234: The type or namespace name 'UI' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)
打开菜单栏 Windows > Package Manager,安装 2D 相关组件