Unity 结合 声网音频SDK做一个【打地猫】小游戏,还可以跟好友们边聊天边撸猫~
@TOC
📢前言
- 前两天刚接触到
声网
的语音通话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
声网
地址在下面,不了解的小伙伴可以简单认识一下~
声网 官网
:https://www.agora.io/cn/community/
首先进去之后需要注册之类的这里就不说了,非常简单~
然后找到下载SDK
的地方:https://docs.agora.io/cn/All/downloads?platform=Unity
声网支持非常多的平台,反正我知道的平台都与声网有合作,不得不说声网还是非常强大的!
然后我们找到Unity的音频SDK
进行下载
下载SDK的时候顺便去 控制台 创建一个项目
由于我们是用来测试使用的,直接选择调试模式就好啦,可以参考官网文档查看二者的区别:https://docs.agora.io/cn/Agora%20Platform/token?platform=All%20Platforms
创建成功后,点击 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
- 自己加班加点搞出来的小项目,还有很多需要完善的地方
- 本篇文章简单介绍了一下,还是很有意思的哈哈! 那咱们下次再见啦!
- 点赞
- 收藏
- 关注作者
评论(0)