unity 使用声网(Agora)实现语音通话

2023-09-13 15:36:20

第一步、先申请一个声网账号
[Agora官网链接](https://console.shengwang.cn/)
第二步在官网创建项目 ,选择无证书模式,证书模式需要tokenh和Appld才能通话
在这里插入图片描述
第三步 官网下载SDK 然后导入到unity,也可以直接在unity商店里下载,Agora官网下载链接
在这里插入图片描述
第四步 运行官方Demo
1、导入后会有这些文件
在这里插入图片描述
2、从官网新建的项目复制AppID,粘贴到这个位置,如果使用的是证书模式,Token也需要填写,否者运行报错110,第三个变量是频道,可以自定义, ,Examples里的场景都是Demo,
在这里插入图片描述
3、找到这个场景,这个是语音通话的Demo场景
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
按照以上步骤,这是运行,就可以实现语音通话了,
如果运行有显示110等错误码,可以查看官网的解决方法,
错误码处理链接

声网每个月有一万分钟免费时长,非常赞
也可以按照官方文档去实现语音通话,文档写的非常清楚,代码都有,我按照吧官方文档的代码粘贴到一个脚本里,运行完全没问题,
上脚本(外加了一些回调事件的补充),

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Agora.Rtc;
using UnityEngine.UI;
using UnityEngine.Serialization;
using Agora_RTC_Plugin.API_Example;
using Logger = Agora_RTC_Plugin.API_Example.Logger;

public class Test : MonoBehaviour
{
    [FormerlySerializedAs("appIdInput")]
    [SerializeField]
    private AppIdInput _appIdInput;
    // 填入你的 app ID。
    private string _appID = "";
    // 填入你的频道名。
    private string _channelName = "";
    // 填入 Token。
    private string _token = "";
    internal IRtcEngine RtcEngine;
    public Text conten;

    internal Logger Log;
    // Start is called before the first frame update
    void Start()
    {
        LoadAssetData();
        if(CheckAppId() )
        {
            SetupVideoSDKEngine();
            InitEventHandler();
            SetupUI();
        }
       
    }
    private void LoadAssetData()
    {
        if (_appIdInput == null) return;
        _appID = _appIdInput.appID;
        _token = _appIdInput.token;
        _channelName = _appIdInput.channelName;
    }

    private bool CheckAppId()
    {
        Log = new Logger(conten);
        return Log.DebugAssert(_appID.Length > 10, "Please fill in your appId in API-Example/profile/appIdInput.asset!!!!!");
    }
    // Update is called once per frame
    void Update()
    {
        CheckPermissions();
    }
    void OnApplicationQuit()
    {
        if (RtcEngine != null)
        {
            Leave();
            // 销毁 IRtcEngine。
            RtcEngine.Dispose();
            RtcEngine = null;
        }
    }
    private void SetupVideoSDKEngine()
    {
        // 创建 IRtcEngine 实例。
        RtcEngine = Agora.Rtc.RtcEngine.CreateAgoraRtcEngine();
        RtcEngineContext context = new RtcEngineContext(_appID, 0, CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT);
        // 初始化 IRtcEngine。
        RtcEngine.Initialize(context);

    }
    // 创建用户回调类实例,并设置回调。
    private void InitEventHandler()
    {
        UserEventHandler handler = new UserEventHandler(this);
        RtcEngine.InitEventHandler(handler);
    }

    private void SetupUI()
    {
        GameObject go = GameObject.Find("Leave");
        go.GetComponent<Button>().onClick.AddListener(Leave);
        go = GameObject.Find("Join");
        go.GetComponent<Button>().onClick.AddListener(Join);
    }
    public void Join()
    {
        Debug.Log("Joining _channelName");
        // 启用音频模块。
        RtcEngine.EnableAudio();
        // 设置频道媒体选项。     
        ChannelMediaOptions options = new ChannelMediaOptions();
        // 自动订阅所有音频流。
        options.autoSubscribeAudio.SetValue(true);
        // 将频道场景设为直播。
        options.channelProfile.SetValue(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING);
        // 将用户角色设为主播。
        options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
        // 加入频道
        // channelKey: 动态秘钥,无证书模式(非安全模式)传入 null;安全模式需要传入服务器生成的 Token
        // channelName: 频道名称
        // info: 开发者附带信息(非必要),不会传递给频道内其他用户
        // uid: 用户ID,0 为自动分配
        RtcEngine.JoinChannel(_token, _channelName, 0, options);
    }
    public void Leave()
    {
       
        Debug.Log("Leaving _channelName");
        // 离开频道。
        RtcEngine.LeaveChannel();
        // 关闭音频模块。
        RtcEngine.DisableAudio();
    }

    private void CheckPermissions()
    {
#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
        foreach (string permission in permissionList)//检查麦克风
        {
            if (!Permission.HasUserAuthorizedPermission(permission))
            {
                Permission.RequestUserPermission(permission);
            }
        }
#endif
    }
}

// 实现你自己的回调类,可以继承 IRtcEngineEventHandler 接口类实现。
internal class UserEventHandler : IRtcEngineEventHandler
{
    private readonly Test _audioSample;

    internal UserEventHandler(Test audioSample)
    {
        _audioSample = audioSample;
    }

    // 发生错误回调。
    public override void OnError(int err, string msg)
    {
    }
    // 当前通话统计回调,每两秒触发一次。
    public override void OnRtcStats(RtcConnection connection, RtcStats stats)
    {
       
    }
    // Token 过期回调
    public override void OnRequestToken(RtcConnection connection)
    {
        
    }
    // Token 即将过期提醒
    public override void OnTokenPrivilegeWillExpire(RtcConnection connection, string token)
    {
        base.OnTokenPrivilegeWillExpire(connection, token);
    }
    /// <summary>
    /// 网络发生变化时的回调
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="state">当前连接的状态</param>
    /// <param name="reason">连接状态改变的原因</param>
    public override void OnConnectionStateChanged(RtcConnection connection, CONNECTION_STATE_TYPE state, CONNECTION_CHANGED_REASON_TYPE reason)
    {
     
    }
   
    // 网络中断回调(建立成功后才会触发)
    public override void OnConnectionInterrupted(RtcConnection connection)
    {
       
    }
    // 网络连接丢失回调
    public override void OnConnectionLost(RtcConnection connection)
    {
        base.OnConnectionLost(connection);
    }
   
    //重新链接网络后加入频道
    public override void OnRejoinChannelSuccess(RtcConnection connection, int elapsed)
    {
     
    }
    // 本地用户成功加入频道时,会触发该回调。
    // channelId:频道名称
    // uid:用户ID(发起请求时候如果没有指定,服务器会自动分配一个)
    // elapsed:从本地用户调用 JoinChannelByKey 到该回调触发的延迟(毫秒)。
    public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
    {
        string joinChannelMessage = string.Format("用户ID:{0},加入频道:{1}", connection.localUid, connection.channelId);
        _audioSample.Log.UpdateLog(joinChannelMessage);
    }
    // 本地用户离开频道的回调
    // stats:通话统计的数据
    //      duration:通话时长
    //      txBytes:发送字节数(bytes)
    //      rxBytes:接收字节数(bytes)
    //      txKBitRate:发送码率(kbps)
    //      rxKBitRate:接收码率(kbps)
    public override void OnLeaveChannel(RtcConnection connection, RtcStats stats)
    {
        string leaveMessage = string.Format("用户ID:{0},离开频道:{1},通话时长:{2}秒", connection.localUid, connection.channelId, stats.duration);
        _audioSample.Log.UpdateLog(leaveMessage);
    }
    // 远端用户成功加入频道时,会触发该回调。
    public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
    {
        string userJoinedMessage = string.Format("远端用户ID:{0},加入频道:{1}", uid, connection.channelId);
        _audioSample.Log.UpdateLog(userJoinedMessage);
    }
    // 远端用户离开当前频道时会触发该回调。
    // reason:离线原因(主动离开、超时、直播模式身份切换)
    public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
    {
        string userOfflineMessage = string.Format("远端用户ID:{0},离开频道:{1}", uid, connection.channelId);
        _audioSample.Log.UpdateLog(userOfflineMessage);
    }
    // 提示频道内谁在说话
    // speakers:说话人信息
    // speakerNumber:说话人数[0,3]
    // totalVolume:总音量
    public override void OnAudioVolumeIndication(RtcConnection connection, AudioVolumeInfo[] speakers, uint speakerNumber, int totalVolume)
    {
        base.OnAudioVolumeIndication(connection, speakers, speakerNumber, totalVolume);
    }
    // 用户静音提示回调
    // uid:用户 ID
    // muted:是否静音
    public override void OnUserMuteAudio(RtcConnection connection, uint remoteUid, bool muted)
    {
        base.OnUserMuteAudio(connection, remoteUid, muted);
    }
  
}

脚本使用方法,新建一个场景,以及搭两个按钮,和一个滑动框,把脚本随便挂载一个物体身上即可,
在这里插入图片描述
ContentSizeFitter可以让UI随文字自适应
在这里插入图片描述
然后运行,点击加入频道,打包PC包,在另一台电脑运行,也点击加入频道。
以下是运行效果,如果另外一台也加入频道,上面会显示远端用户加入频道,
在这里插入图片描述

借鉴的文章
这个文章里有视频通话,需要的小伙伴可以看这个

更多推荐

基于改进莱维飞行和混沌映射的粒子群优化BP神经网络预测股票价格研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。⛳️座右铭:行百里者,半于九十。📋📋📋本文目录如下:🎁🎁🎁目录💥1概述📚2运行结果🎉3参考文献🌈4Matlab代码实现💥1概述基于改进莱维飞行和混沌映射的粒子群优化BP神经网络

SunTorque亮相GAF2023数字化智能装配工程与装备技术大会

智能扭矩系统-智能拧紧系统-智能扭矩控制-SunTorqueGAF2023数字化智能装配工程与装备技术大会在中国上海汽车会展中心盛大开幕,青创智通与装配领域、智能制造、数字化应用等相关先进智造技术的知名企业一齐亮相。本次展会,我们带来了扭矩相关解决方案,包含智能扭矩系统软件、工具存储设备、扭矩校验设备、智能手持终端、扭

neo4j下载安装配置步骤

目录一、介绍简介Neo4j和JDK版本对应二、下载官网下载直接获取三、解压缩安装四、配置环境变量五、启动测试一、介绍简介Neo4j是一款高性能的图数据库,专门用于存储和处理图形数据。它采用节点、关系和属性的图形结构,非常适用于表示和查询复杂的实体关系。Neo4j具有高性能、事务支持、可扩展性和直观的Cypher查询语言

喜报 | 亮相2023数博会,摘得首届数智金融创新大赛优秀奖

河北正定,千年古城,这里不仅有一幕幕刀光剑影,鼓角争鸣的故事,还有驰名中外的人“一寺四塔”,有宜人的气候,也有汇聚高科技的天下英雄会。图源于网络2023年9月6日,河北正定,中国国际数字经济博览会(以下简称数博会)正式开幕,坚定“工业互联网赋能千行百业”的科技信仰,奔向“数字经济引领高质量发展”的未来世界。图源于网络据

探索小程序的世界(专栏导读、基础理论)

文章导读一、为什么要学习小程序开发1.1低门槛1.2市场需求1.3创业机会1.4技术发展趋势二、专栏导读2.1实战系列2.2工具系列2.3游戏系列2.4插件系列三、基础理论3.1微信小程序简易教程框架组件API工具开发者工具项目结构3.2app.json配置pageswindowtabbar3.3App.jsonLau

k8备份与恢复-Velero

简介Velero是一款可以安全的备份、恢复和迁移Kubernetes集群资源和持久卷等资源的备份恢复软件。Velero实现的kubernetes资源备份能力,可以轻松实现Kubernetes集群的数据备份和恢复、复制kubernetes集群资源到其他kubernetes集群或者快速复制生产环境到测试环境等功能,这种备份

4. algorithm

algorithm书写1.algorithm2.algorithm2e1.algorithm在LaTeX中,要显示算法,您可以使用algorithm宏包来排版算法,并使用algorithmic宏包来编写算法的伪代码。以下是显示算法的基本步骤:导入宏包:在LaTeX文档的导言区(preamble)中,导入algorith

idea集成tomcat(Smart Tomcate插件安装)

当我们在tomcat上部署好一个webapp后,如果我们要修改代码,就需要重新进行打包和部署,但往往在工作中是需要频繁修改代码,然后再查看成果的,就需要反复的进行打包和部署的过程,这是很麻烦的通过SmartTomcate插件我们就能解决这个问题,可以直接使用idea图形化界面把代码部署到tomcat上达成“一键打包&部

Windows服务器设置Nginx实现分布式服务

1.安装Nginx下载Nginx-1.16.1版本。解压到如下目录:设置环境变量:检查版本:启动nginx.exe,出现黑框一闪而过,进程中出现如下情况代表启动成功:2.搭建模拟HTTP服务下载wiremock-standalone-2.25.1.jar,可以使用Maven配置pom.xml下载。注意下载standal

JavaWeb后端开发 JWT令牌解析 登录校验 通用模板/SpringBoot整合

目录实现思路相关技术的解析​编辑会话跟踪三个方案JWT令牌技术​生成令牌校验令牌登录下发令牌实现思路通过登录成功的标记来检测,在每个接口前做一个标记判断是否登录,若没登录则返回错误信息,并使前端退出.但这样较为繁琐,因此我们可以通过一种统一拦截的技术来拦截所有请求.相关技术的解析会话跟踪的三个方案1.访问cookie的

Nginx替代产品-Tengine健康检测

1、官网地址官网地址:TheTengineWebServer文档地址:文档-TheTengineWebServer健康检测模块:ngx_http_upstream_check_module-TheTengineWebServer2、安装下载wgethttps://tengine.taobao.org/download/

热文推荐