她
文章目录
- 一、 介绍
- 二、 重点知识点和游戏逻辑
- 三、 箭头脚本
- 四、 管理箭头脚本
- 五、 管理全局脚本
- 六、 管理玩家输入脚本
- 七、 ui脚本
- 八、 制作动画
- 九、 添加音乐节奏
- 十、 工程下载
一、 介绍
QQ炫舞是由腾讯公司开发的一款音乐舞蹈网游,玩家可以在游戏中扮演自己的虚拟角色,跳舞展示自己的舞技,与其他玩家互动。游戏包括多种不同风格的舞曲,玩家可以通过完成任务或购买道具获得更多舞曲和装扮。
本文模拟qq炫舞游戏的核心玩法。
玩家输入上下左右按键、按空格结束,成功后角色播放动画,跳到下一个level,箭头数量+1。
二、 重点知识点和游戏逻辑
1.单例模式
2.使用“队列”数据结构
3.Arrows Holder组件
4.动画混合器
5.协程
三、 箭头脚本
生成单个箭头
绿色箭头是终点
using System.Collections;
using System.Collections.Generic; // 引入命名空间using UnityEngine;
using UnityEngine.UI;public class Arrow : MonoBehaviour // 定义了一个名为 Arrow 的类,并继承自 MonoBehaviour 类
{public Sprite[] arrowSprites; // 公有变量,类型为 Sprite 数组,用于存储箭头的图像资源Image image; // 私有变量,类型为 Image,用于引用箭头的 Image 组件[HideInInspector]public int arrowDir; // 公有整型变量,用于存储箭头的朝向public Color finishColor; // 公有变量,类型为 Color,定义了箭头到达终点时的颜色private void Awake(){image = GetComponent<Image>(); // 获取当前 GameObject 上的 Image 组件}public void Setup(int dir) // 定义了一个公有方法,用于设置箭头的朝向以及显示箭头的图像{arrowDir = dir; image.sprite = arrowSprites[dir]; // 设置 Image 组件的 sprite 属性为 arrowSprites 数组中对应索引的 Sprite 对象image.SetNativeSize(); // 根据 Sprite 图像的大小调整 Image 组件的大小}public void SetFinish() // 定义了一个公有方法,用于将箭头的颜色更改为定义的终点颜色{image.color = finishColor; // 更改 Image 组件的 color 属性为定义好的终点颜色}
}
四、 管理箭头脚本
生成一组箭头
队列加入箭头
箭头方向转换
判断箭头方向
销毁所有箭头
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ArrowManager : MonoBehaviour
{public static ArrowManager S; // 单例实例private void Awake(){S = this; // 初始化单例实例}public GameObject arrowPrefab; // 箭头预制体public Transform arrowsHolder; // 箭头容器public static bool isFinish; // 是否完成当前波次Queue<Arrow> arrows = new Queue<Arrow>(); // 箭头队列Arrow currentArrow; // 当前需要敲击的箭头public void CreateWave(int length){arrows = new Queue<Arrow>(); // 初始化箭头队列isFinish = false; // 重置是否完成当前波次的标志for (int i = 0; i < length; i++){Arrow arrow = Instantiate(arrowPrefab, arrowsHolder).GetComponent<Arrow>(); // 实例化箭头预制体int randomDir = Random.Range(0, 4); // 随机生成箭头方向arrow.Setup(randomDir); // 初始化箭头arrows.Enqueue(arrow); // 将箭头添加到队列中}currentArrow = arrows.Dequeue(); // 取出队列中的第一个箭头作为当前需要敲击的箭头}public void TypeArrow(KeyCode inputKey){if (ConvertKeyCodeToInt(inputKey) == currentArrow.arrowDir) // 判断是否敲击正确{//Type CorrectlycurrentArrow.SetFinish(); // 标志当前箭头已被敲击正确if (arrows.Count > 0) // 如果队列中还有箭头{currentArrow = arrows.Dequeue(); // 取出队列中的下一个箭头作为当前需要敲击的箭头}else // 如果队列中没有箭头了{isFinish = true; // 标志完成当前波次}}else // 如果敲击错误{GameManager.S.FailWave(); // 通知 GameManager 波次失败}}public void ClearWave(){arrows = new Queue<Arrow>(); // 初始化箭头队列foreach(Transform arrow in arrowsHolder) // 销毁箭头容器中的所有箭头{Destroy(arrow.gameObject);}}int ConvertKeyCodeToInt(KeyCode key){int result = 0;switch(key) // 将 KeyCode 转换为 int 类型的箭头方向{case KeyCode.UpArrow:{result = 0;break;}case KeyCode.DownArrow:{result = 1;break;}case KeyCode.LeftArrow:{result = 2;break;}case KeyCode.RightArrow:{result = 3;break;}}return result; // 返回转换后的箭头方向}
}
五、 管理全局脚本
管理全局,负责控制节拍、动画控制、播放音乐、下一关生成
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GameManager : MonoBehaviour
{public static GameManager S; // 单例实例private void Awake(){S = this; // 初始化单例实例}int currentLevel = 5; // 当前等级public static bool isDancing; // 是否正在跳舞//public Animator anim; // 动画控制器public int bpm; // 每分钟节拍数public float startDelay; // 延迟播放音乐的时间public AudioSource au; // 音频源private void Start(){NextWave(); // 进入下一波//Invoke("PlaySound", startDelay); // 延迟播放音乐}void PlaySound(){au.Play(); // 播放音乐}void NextWave(){UIManager.S.ShowOrHidePointer(); // 隐藏箭头指针UIManager.S.RenewLevelText(currentLevel); // 更新等级显示ArrowManager.S.CreateWave(currentLevel); // 创建新的箭头波次isDancing = true; // 进入跳舞状态}public void FinishWave(){currentLevel++; // 升级isDancing = false; // 退出跳舞状态ArrowManager.S.ClearWave(); // 清除箭头波次UIManager.S.ShowOrHidePointer(); // 显示箭头指针//anim.SetFloat("Dance", Random.Range(0.01f, 1f)); // 随机设置动画参数}public void FailWave(){isDancing = false; // 退出跳舞状态ArrowManager.S.ClearWave(); // 清除箭头波次UIManager.S.ShowOrHidePointer(); // 显示箭头指针//anim.SetFloat("Dance", -0.01f); // 设置动画参数}public void PointerIsReset(){if (isDancing)FailWave(); // 失败elseNextWave(); // 进入下一波}
}
六、 管理玩家输入脚本
玩家输入上下左右、空格。
如果输入错误、按得太快、按得太慢,重新加载当前关卡
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class InputManager : MonoBehaviour
{public static InputManager S; // 单例实例private void Awake(){S = this; // 初始化单例实例}void Update(){if (!GameManager.isDancing) // 如果没有在跳舞,直接返回return;if (Input.GetKeyDown(KeyCode.UpArrow)) // 如果按下了上箭头键ArrowManager.S.TypeArrow(KeyCode.UpArrow); // 处理上箭头if (Input.GetKeyDown(KeyCode.DownArrow)) // 如果按下了下箭头键ArrowManager.S.TypeArrow(KeyCode.DownArrow); // 处理下箭头if (Input.GetKeyDown(KeyCode.LeftArrow)) // 如果按下了左箭头键ArrowManager.S.TypeArrow(KeyCode.LeftArrow); // 处理左箭头if (Input.GetKeyDown(KeyCode.RightArrow)) // 如果按下了右箭头键ArrowManager.S.TypeArrow(KeyCode.RightArrow); // 处理右箭头if(Input.GetKeyDown(KeyCode.Space)) // 如果按下了空格键{if (ArrowManager.isFinish && UIManager.S.CheckPointerIsInSweetSpot()) // 如果当前波次已完成并且箭头指针在甜点区域内GameManager.S.FinishWave(); // 完成当前波次elseGameManager.S.FailWave(); // 失败当前波次}}
}
七、 ui脚本
制作ui
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class UIManager : MonoBehaviour
{public static UIManager S; // 单例实例private void Awake(){S = this; // 初始化单例实例}public Text levelText; // 显示等级的文本框public Transform pointer, sweetSpot; // 箭头指针和甜点区域的位置public Transform startPos, endPos; // 指针移动的起始位置和终止位置public float pointerMoveSpeed; // 指针移动的速度private void Start(){// 根据bpm和节拍计算指针移动的速度pointerMoveSpeed = (endPos.position.x - startPos.position.x) / (60f / GameManager.S.bpm * 8f);}private void Update(){// 每帧将指针向右移动一定距离pointer.position += Vector3.right * pointerMoveSpeed * Time.deltaTime;// 如果指针移动到了终止位置,将指针重置到起始位置if (pointer.position.x > endPos.position.x)ResetPointer();}// 将指针重置到起始位置void ResetPointer(){pointer.position = startPos.position;GameManager.S.PointerIsReset();}// 显示或隐藏指针public void ShowOrHidePointer(){pointer.gameObject.SetActive(!pointer.gameObject.activeInHierarchy);}// 检查指针是否在甜点区域内public bool CheckPointerIsInSweetSpot(){return Mathf.Abs((pointer.position.x - sweetSpot.position.x)) < 25f;}// 更新等级文本public void RenewLevelText(int level){levelText.text = "LEVEL " + level;}
}
八、 制作动画
下载动画模型
https://www.mixamo.com/#/?page=1&query=
创建混合树,随机生成数值,控制动画播放
九、 添加音乐节奏
添加不同的背景音乐,根据音乐调节节奏
设置滑动条滚动速度
private void Start()
{pointerMoveSpeed = (endPos.position.x - startPos.position.x) / (60f / GameManager.S.bpm * 8f);
}
十、 工程下载
https://wwez.lanzoul.com/ifDh20t2ef7i