益智类小游戏保护小猫做一个暖心的铲屎官,还有语音聊天功能文末送书
Posted 呆呆敲代码的小Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了益智类小游戏保护小猫做一个暖心的铲屎官,还有语音聊天功能文末送书相关的知识,希望对你有一定的参考价值。
🍕引言
- 小伙伴们好久不见,今天给大家带来一个
保护小猫
的小游戏源码分享 完整项目源码
在文末可以直接下载体验,也可以关注文末卡片
获取更多源码!- 下面来对这个小游戏的工程源码,简单分析一下
- 这里就不一步一步来演示啦,主要是分享源码~
🎄【小游戏】保护小猫 效果展示+完整项目源码
先来看一下游戏效果
吧
游戏效果展示:
核心玩法
就是使用鼠标控制一个方块来保护小猫不被障碍物碰到
小猫会不停的想上攀爬来计算分数,当碰到障碍物的时候比赛就会结束了!
非常考验玩家的反应和手速哦哈哈,反正我玩一会就GG了~
😻游戏图片
先来看几张游戏内的截图,包括开始时的画面,游戏中和游戏结束等画面
如下所示:
😺工程解析
下面来看一下工程目录结构如下:
- _Prefabs:预制体
- _Scenes:场景文件夹
- _Scripts:放脚本的文件夹
- _Sprites:放精灵图片的文件夹
- Animations:动画控制器文件夹
- Common:通用素材和脚本的文件夹
- Music_Sound:存放音频的文件夹
- Plugins:存放插件的文件夹
- Resources:存放加载文件的文件夹
预制体
的话主要就是游戏中的一些UI元素,因为这是一个2D游戏,所以UI中用到的素材、预制体等都是UI了
场景
声网话只有一个主场景,因为游戏很简单,所以包括开始界面和游戏界面都是在同一个场景中完成的!
脚本
的话有十来个,控制游戏的一个运行逻辑过程!
精灵图片
有很多,会在游戏过程进行不断的切换达到一个视觉效果~
还有就是音频文件夹
了,主要是有一个背景音乐、一个开始和结束的音效
Resources文件夹
中的东西比较重要,因为我们在玩这个小游戏的时候,一个核心的玩法就是场景是随机进行变化处理的
这里是预先做好了很多个预制体模型,用于在游戏过程中随机进行生成达到一个增加游戏可玩性
的效果
这也是这个小游戏最核心的可玩性机制
了,如果每次刷新的障碍物都是一样的,那么这个小游戏确实也没啥好玩的哈哈~
😹核心代码讲解
这个工程有两个游戏控制器Controller
,分别是 MainController
和HomeController
HomeController
中的内容比较简单
MainController
是控制游戏运行的一个核心控制器,控制核心的障碍的加载方法、背景图片的切换和加载
以及新关卡加载、开始、暂停、继续、结束游戏的逻辑处理和UI的实时更新等功能
是整个游戏运行的核心脚本,部分代码如下:
public class MainController : BaseController
public Transform backRegion, spawnRegion;
public BackItem backPrefab;
public List<GroupObstacle> obstaclePrefabs;
private int colorIndex = 0, backCount = 0;
private BackItem lastBack = null;
public enum GameState START, LOADED, PLAYING, GAME_OVER, COMPLETED, GUIDE, SHOP, PAUSED;
public static GameState gameState = GameState.START, lastState = GameState.START;
public GameObject startFrame, guideFrame, shopFrame, gameTitle;
public Protection protection;
public ChallengeController challengeController;
public ClassicController classicController;
public static MainController instance;
public ContinueFrame continueFrame;
public MyPlayer player;
private int spawnLevel = 1, passedLevel = 0, currentLevel = 0;
private int savedObstacleIndex, lastObstacleIndex;
public Animator flash;
private List<BackItem> backs = new List<BackItem>();
protected override void Awake()
base.Awake();
instance = this;
protected override void Start()
base.Start();
SetupBackground();
LoadAllObstacles();
private void LoadAllObstacles()
obstaclePrefabs = Resources.LoadAll<GroupObstacle>("GroupObstacles").ToList();
obstaclePrefabs.Sort((x, y) => Utils.GetGroupObIndex(x.name).CompareTo(Utils.GetGroupObIndex(y.name)));
private void SetupBackground()
lastBack = SpawnNewBackground(Vector3.zero);
lastBack.SetUp(0, 5, true, true, 0);
backs.Add(lastBack);
colorIndex = Random.Range(1, 5);
float canvasHeight = backRegion.parent.GetComponent<RectTransform>().sizeDelta.y;
for (int i = 0; i < 2; i++)
Vector3 pos = new Vector3(0, lastBack.rect.anchoredPosition.y + (i == 0 ? canvasHeight : Const.BACK_HEIGHT));
lastBack = SpawnNewBackground(pos);
lastBack.SetUp(colorIndex, colorIndex, i == 0, false, 1);
backs.Add(lastBack);
MyPlayer
脚本是挂载到我们的小猫咪身上的,主要是控制 图标的切换 以及 猫咪身上的碰撞体 相关的逻辑
在碰到障碍物的时候触发游戏结束的事件,进行相关逻辑的处理!
public SpriteRenderer icon;
public Sprite[] iconSprites;
public GameObject playerIconPrefab;
public GameObject bubble;
public GameObject[] bubbleParts;
void Start()
UpdateSprite();
public void UpdateSprite()
int selectedType = CUtils.GetPlayerType();
icon.sprite = iconSprites[selectedType];
void OnCollisionEnter2D(Collision2D collision)
if (collision.collider.tag == "Obstacle" && MainController.IsPlaying())
MainController.instance.CollideWithObstacle();
MainController.instance.CheckAndShowContinue();
icon.gameObject.SetActive(false);
GetComponent<CircleCollider2D>().isTrigger = true;
bubble.SetActive(false);
foreach (GameObject p in bubbleParts)
p.SetActive(true);
GetComponent<Animator>().SetTrigger("Break");
Sound.instance.Play(Sound.Others.Break);
Timer.Schedule(this, 0.5f, () =>
Sound.instance.Play(Sound.Others.Die);
);
SpawnIcon();
private void SpawnIcon()
GameObject obj = (GameObject)Instantiate(playerIconPrefab);
obj.transform.localPosition = icon.transform.position;
obj.GetComponent< SpriteRenderer>().sprite = iconSprites[CUtils.GetPlayerType()];
obj.transform.localScale = Vector3.one * 0.5f;
public void Reset()
icon.gameObject.SetActive(true);
GetComponent<CircleCollider2D>().isTrigger = false;
bubble.SetActive(true);
foreach(GameObject p in bubbleParts)
p.SetActive(false);
其他的代码就不一一讲解了。喜欢这个小游戏的可以下载源码工程娱乐一下
虽然是个小游戏,总共有十几个脚本组成,但是还是挺有可玩性的!
😼接入声网音频SDK
小游戏的核心玩法解决了,下面我们再给他加上声网的音频SDK
实现一个语音聊天
的功能!
接入代码非常简单,只需要去声网下载音频通话的SDK,并创建项目获取 APP ID
就好了!
这是下载SDK
的地方:https://docs.agora.io/cn/All/downloads?platform=Unity
然后我们找到Unity的音频SDK
进行下载
然后去 控制台 创建一个项目
直接选择调试模式
,创建成功后,点击 将 APP ID
复制出来,后面会用到!
现在我们已经拿到声网音频的SDK和项目的 APP ID
了,接下来就是把这个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) =>
以上是关于益智类小游戏保护小猫做一个暖心的铲屎官,还有语音聊天功能文末送书的主要内容,如果未能解决你的问题,请参考以下文章