Unity 接入 声网SDK 做一个【打地猫😹】小游戏,还可以跟好友们边聊天边撸猫!

1,655 阅读5分钟

一起用代码吸猫!本文正在参与【喵星人征文活动】


📢前言

  • 前两天刚接触到 声网 的语音通话SDK,觉得很有意思

  • 那今天就给大家带来一个【打地猫】小游戏

  • 顺带接入声网SDK,实现一个世界聊天频道的功能!


🎬【打地猫】 小游戏

这个小游戏其实很简单,三个脚本搞定,还是挺有意思的!

小猫咪们随机跳出来,然后我们拿着锤子暴击小猫咪哈哈

然后还有一个世界聊天频道,使用声网SDK实现,也非常简单,文中都介绍了怎样接入

赶紧一起来看看吧!先来看一下效果图:

请添加图片描述

下面来讲一下这个小游戏的制作步骤!


第1️⃣步:搭建场景和模型配置

这一步很简单,先随便搭建一个场景

因为是打地猫嘛,所以加几个坑位用来让小猫咪跳出来让我们打!

然后加一个锤子在上面,当我们鼠标点击的时候就进行击打就好啦!

在这里插入图片描述

然后再把小猫咪藏到坑位下面,待会写一个脚本让他自己跳出来让我们打就好了

在这里插入图片描述


第2️⃣步:编写脚本,让猫咪自动跳出

代码很简单,先声明猫咪的几种状态,比如:在底下、在上面、被击打等

然后我们写一个判定条件,让猫咪在不同的状态时做不同的事情!

核心代码如下:

	enum State{
		UNDER_GROUND,
		UP,
		ON_GROUND,
		DOWN,
		HIT,
	}
	State state;

void Update () 
	{

		if (this.state == State.UP) 
		{
			transform.Translate (0, this.moveSpeed, 0);

			if (transform.position.y > TOP) 
			{
				transform.position = 
					new Vector3 (transform.position.x, TOP, transform.position.z);

				this.state = State.ON_GROUND;

				this.tmpTime = 0;
			}
		} 
		else if (this.state == State.ON_GROUND)
		{
			this.tmpTime += Time.deltaTime;

			if (this.tmpTime > this.waitTime) 
			{
				this.state = State.DOWN;
			}
		}
		else if (this.state == State.DOWN) 
		{
			transform.Translate (0, -this.moveSpeed, 0);

			if (transform.position.y < BOTTOM) 
			{
				transform.position = 
					new Vector3(transform.position.x, BOTTOM, transform.position.z);

				this.state = State.UNDER_GROUND;
			}
		}
	}

这样我们的小猫咪就可以根据不同的状态显示不同的效果了!


第3️⃣步:鼠标点击 击打的代码

因为我们做的效果是鼠标点哪里,锤子就往哪里打 所以这里给锤子加一个脚本,让他在鼠标点击的时候就跟随鼠标的坐标进行击打!

核心代码如下:

void Update () 
	{
		if(Input.GetMouseButtonDown(0))
		{
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			RaycastHit hit;

			if (Physics.Raycast(ray, out hit, 100)) 
			{
				GameObject mole = hit.collider.gameObject;
					
				bool isHit = mole.GetComponent<MoleController> ().Hit ();

				// if hit the mole, show hummer and effect
				if (isHit) 
				{
					StartCoroutine (Hit (mole.transform.position));

					ScoreManager.score += 10;
				}
			}
		}
	}

第4️⃣步,加一个随机让小猫咪跳出的脚本

我们第一步中写了小猫会根据不同的状态做不同的事

还需要写一个脚本用于控制小猫的随机跳出,这样增加游戏可玩性!

核心代码如下:

IEnumerator Generate()
	{
		this.generate = true;

		while (this.generate) 
		{
			// wait to generate next group
			yield return new WaitForSeconds (1.0f);

			int n = moles.Count;
			int maxNum = (int)this.maxMoles.Evaluate ( GameManager.time );

			for (int i = 0; i < maxNum; i++) 
			{
				// select mole to up
				this.moles [Random.Range (0, n)].Up ();
								
				yield return new WaitForSeconds (0.3f);
			}
		}
	}

这样我们的小游戏就算完成啦!但是还没有加入声网的SDK实现一个世界聊天频道的功能

所以接着往下看!


第5️⃣步:去声网下载音频通话的SDK,并创建项目获取APP ID

声网地址在下面,不了解的小伙伴可以简单认识一下~

声网 官网www.agora.io/cn/communit…

首先进去之后需要注册之类的这里就不说了,非常简单~

然后找到下载SDK的地方:docs.agora.io/cn/All/down…

声网支持非常多的平台,反正我知道的平台都与声网有合作,不得不说声网还是非常强大的!

然后我们找到Unity的音频SDK进行下载 在这里插入图片描述 下载SDK的时候顺便去 控制台 创建一个项目 在这里插入图片描述 由于我们是用来测试使用的,直接选择调试模式就好啦,可以参考官网文档查看二者的区别:docs.agora.io/cn/Agora%20…

创建成功后,点击 APP ID 按钮,将其复制出来,后面的代码中会用到! 在这里插入图片描述


第6️⃣步:将声网音频SDK接入到项目中

在上一步中,我们已经把音频SDK下好了,里面还有一个示例工程

方便我们接入的时候可以进行学习!

这里我们直接把下载的SDK放到我们的工程中就可以了

然后我们新建一个脚本用来管理世界聊天频道

核心代码如下:

using UnityEngine;
using UnityEngine.UI;
#if(UNITY_2018_3_OR_NEWER)
using UnityEngine.Android;
#endif
using agora_gaming_rtc;

public class HelloUnity3D : MonoBehaviour
{
    private InputField mChannelNameInputField;//频道号
    public Text mShownMessage;//提示
    private Text versionText;//版本号
    public Button joinChannel;//加入房间
    public Button leaveChannel;//离开房间
    private Button muteButton;//静音

    private IRtcEngine mRtcEngine = null;

    // 输入App ID后,在App ID外删除##
    [SerializeField]
    private string AppID = "app_id";

    void Awake()
    {
        QualitySettings.vSyncCount = 0;
        Application.targetFrameRate = 30;
        //muteButton.enabled = false;
        CheckAppId();
    }

    // 进行初始化
    void Start()
    {
#if (UNITY_2018_3_OR_NEWER)
        // 判断是否有麦克风权限,没有权限的话主动申请权限
			if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
			{
            Permission.RequestUserPermission(Permission.Microphone);
            } 

#endif
        joinChannel.onClick.AddListener(JoinChannel);
        leaveChannel.onClick.AddListener(LeaveChannel);
        //muteButton.onClick.AddListener(MuteButtonTapped);

        mRtcEngine = IRtcEngine.GetEngine(AppID);
        //versionText.GetComponent<Text>().text = "Version : " + getSdkVersion();

        //加入频道成功后的回调
        mRtcEngine.OnJoinChannelSuccess += (string channelName, uint uid, int elapsed) =>
        {
            string joinSuccessMessage = string.Format("加入频道 回调 uid: {0}, channel: {1}, version: {2}", uid, channelName, getSdkVersion());
            Debug.Log(joinSuccessMessage);
            mShownMessage.GetComponent<Text>().text = (joinSuccessMessage);
            //muteButton.enabled = true;
        };

        //离开频道回调。 
        mRtcEngine.OnLeaveChannel += (RtcStats stats) =>
        {
            string leaveChannelMessage = string.Format("离开频道回调时间 {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate);
            Debug.Log(leaveChannelMessage);
            mShownMessage.GetComponent<Text>().text = (leaveChannelMessage);
            //muteButton.enabled = false;
            // 重置静音键状态
            //if (isMuted)
           // {
          //      MuteButtonTapped();
            //}
        };

        //远端用户加入当前频道回调。 
        mRtcEngine.OnUserJoined += (uint uid, int elapsed) =>
        {
            string userJoinedMessage = string.Format("远端用户加入当前频道回调 uid {0} {1}", uid, elapsed);
            Debug.Log(userJoinedMessage);
            mShownMessage.GetComponent<Text>().text = (userJoinedMessage);
        };

        //远端用户离开当前频道回调。 
        mRtcEngine.OnUserOffline += (uint uid, USER_OFFLINE_REASON reason) =>
        {
            string userOfflineMessage = string.Format("远端用户离开当前频道回调 uid {0} {1}", uid, reason);
            Debug.Log(userOfflineMessage);
            mShownMessage.GetComponent<Text>().text = (userOfflineMessage);
        };

        // 	用户音量提示回调。 
        mRtcEngine.OnVolumeIndication += (AudioVolumeInfo[] speakers, int speakerNumber, int totalVolume) =>
        {
            if (speakerNumber == 0 || speakers == null)
            {
                Debug.Log(string.Format("本地用户音量提示回调   {0}", totalVolume));
            }

            for (int idx = 0; idx < speakerNumber; idx++)
            {
                string volumeIndicationMessage = string.Format("{0} onVolumeIndication {1} {2}", speakerNumber, speakers[idx].uid, speakers[idx].volume);
                Debug.Log(volumeIndicationMessage);
            }
        };

        //用户静音提示回调
        mRtcEngine.OnUserMutedAudio += (uint uid, bool muted) =>
        {
            string userMutedMessage = string.Format("用户静音提示回调 uid {0} {1}", uid, muted);
            Debug.Log(userMutedMessage);
            mShownMessage.GetComponent<Text>().text = (userMutedMessage);
        };

        //发生警告回调
        mRtcEngine.OnWarning += (int warn, string msg) =>
        {
            string description = IRtcEngine.GetErrorDescription(warn);
            string warningMessage = string.Format("发生警告回调 {0} {1} {2}", warn, msg, description);
            Debug.Log(warningMessage);
        };

        //发生错误回调
        mRtcEngine.OnError += (int error, string msg) =>
        {
            string description = IRtcEngine.GetErrorDescription(error);
            string errorMessage = string.Format("发生错误回调 {0} {1} {2}", error, msg, description);
            Debug.Log(errorMessage);
        };

        // 当前通话统计回调,每两秒触发一次。
        mRtcEngine.OnRtcStats += (RtcStats stats) =>
        {
            string rtcStatsMessage = string.Format("onRtcStats callback duration {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}, tx(a) kbps: {5}, rx(a) kbps: {6} users {7}",
                stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate, stats.txAudioKBitRate, stats.rxAudioKBitRate, stats.userCount);
            //Debug.Log(rtcStatsMessage);

            int lengthOfMixingFile = mRtcEngine.GetAudioMixingDuration();
            int currentTs = mRtcEngine.GetAudioMixingCurrentPosition();

            string mixingMessage = string.Format("Mixing File Meta {0}, {1}", lengthOfMixingFile, currentTs);
            //Debug.Log(mixingMessage);
        };

        //语音路由已发生变化回调。(只在移动平台生效)
        mRtcEngine.OnAudioRouteChanged += (AUDIO_ROUTE route) =>
        {
            string routeMessage = string.Format("onAudioRouteChanged {0}", route);
            Debug.Log(routeMessage);
        };

        //Token 过期回调
        mRtcEngine.OnRequestToken += () =>
        {
            string requestKeyMessage = string.Format("OnRequestToken");
            Debug.Log(requestKeyMessage);
        };

        // 网络中断回调(建立成功后才会触发)
        mRtcEngine.OnConnectionInterrupted += () =>
        {
            string interruptedMessage = string.Format("OnConnectionInterrupted");
            Debug.Log(interruptedMessage);
        };

        // 网络连接丢失回调
        mRtcEngine.OnConnectionLost += () =>
        {
            string lostMessage = string.Format("OnConnectionLost");
            Debug.Log(lostMessage);
        };

        // 设置 Log 级别
        mRtcEngine.SetLogFilter(LOG_FILTER.INFO);

        // 1.设置为自由说话模式,常用于一对一或者群聊
        mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_COMMUNICATION);

        //2.设置为直播模式,适用于聊天室或交互式视频流等场景。
        //mRtcEngine.SetChannelProfile (CHANNEL_PROFILE.CHANNEL_PROFILE_LIVE_BROADCASTING);

        //3.设置为游戏模式。这个配置文件使用较低比特率的编解码器,消耗更少的电力。适用于所有游戏玩家都可以自由交谈的游戏场景。
        //mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_GAME);

        //设置直播场景下的用户角色。 
        //mRtcEngine.SetClientRole (CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
    }

    private void CheckAppId()
    {
        Debug.Assert(AppID.Length > 10, "请先在Game Controller对象上填写你的AppId。.");
        GameObject go = GameObject.Find("AppIDText");
        if (go != null)
        {
            Text appIDText = go.GetComponent<Text>();
            if (appIDText != null)
            {
                if (string.IsNullOrEmpty(AppID))
                {
                    appIDText.text = "AppID: " + "UNDEFINED!";
                    appIDText.color = Color.red;
                }
                else
                {
                    appIDText.text = "AppID: " + AppID.Substring(0, 4) + "********" + AppID.Substring(AppID.Length - 4, 4);
                }
            }
        }
    }

    /// <summary>
    /// 加入频道
    /// </summary>
    public void JoinChannel()
    {
        // 从界面的输入框获取频道名称
        string channelName = "adc666";

        // 从界面的输入框获取频道名称
        //string channelNameOld = mChannelNameInputField.text.Trim();

        Debug.Log(string.Format("从界面的输入框获取频道名称 {0}", channelName));

        if (string.IsNullOrEmpty(channelName))
        {
            return;
        }
        // 加入频道
        // channelKey: 动态秘钥,我们最开始没有选择 Token 模式,这里就可以传入 null;否则需要传入服务器生成的 Token
        // channelName: 频道名称
        // info: 开发者附带信息(非必要),不会传递给频道内其他用户
        // uid: 用户ID,0 为自动分配
        mRtcEngine.JoinChannelByKey(channelKey: null, channelName: channelName, info: "extra", uid: 0);

        //加入频道并设置发布和订阅状态。 
        //mRtcEngine.JoinChannel(channelName, "extra", 0);
    }

    /// <summary>
    ///  离开频道
    /// </summary>
    public void LeaveChannel()
    {
        // 离开频道
        mRtcEngine.LeaveChannel();

        string channelName = "abc666";
        Debug.Log(string.Format("left channel name {0}", channelName));
    }

    void OnApplicationQuit()
    {
        if (mRtcEngine != null)
        {
            // 销毁 IRtcEngine
            IRtcEngine.Destroy();
        }
    }

    /// <summary>
    /// 查询 SDK 版本号。 
    /// </summary>
    /// <returns></returns>
    public string getSdkVersion()
    {
        string ver = IRtcEngine.GetSdkVersion();
        return ver;
    }


    bool isMuted = false;
    void MuteButtonTapped()
    {
        //设置静音或者取消静音
        string labeltext = isMuted ? "静音" : "取消静音";
        Text label = muteButton.GetComponentInChildren<Text>();

        if (label != null)
        {
            label.text = labeltext;
        }
        isMuted = !isMuted;
        // 设置静音(停止推送本地音频)
        mRtcEngine.EnableLocalAudio(!isMuted);
        Debug.Log("静音方法执行完成");
    }
}

这里我把默认频道设置好了,等于所有人点击的时候都进入一个频道进行聊天

但是这样是不好的!这里图个方便就这样办了~

到这里就大功告成了,我们已经实现了在这个打地猫的小游戏中加入了世界聊天频道功能!

虽然功能可能不够完善,后边多用几次就熟悉了嘿嘿!


总结

  • 本文做了一个简单的打地猫小游戏,顺道接入了声网的音频SDK

  • 自己加班加点搞出来的小项目,还有很多需要完善的地方

  • 本篇文章简单介绍了一下,还是很有意思的哈哈! 那咱们下次再见啦!

请添加图片描述