一、框架视图
二、关键代码
ViewMusic
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ViewMusic : MonoBehaviour
{
public Transform[] boxTransforms = new Transform[64];
public int isRight = 1;
public AudioSource audioSource;
public float[] sepctrumData = new float[64];
public MeshRenderer[] meshRenderers = new MeshRenderer[64];
public int UpLerp = 12;
void Start()
{
SetCunbeInfo();
}
// Update is called once per frame
void Update()
{
audioSource.GetSpectrumData(sepctrumData, 0, FFTWindow.BlackmanHarris);
SetScale();
SetColor();
}
public void SetCunbeInfo()
{
Array.Clear(boxTransforms, 0, 64);
Array.Clear(meshRenderers, 0, 64);
for(int i=0;i<64;i++)
{
transform.GetChild(i).position = new Vector3(5 * isRight, 2.5f, 6.5f + 0.25f * i);
transform.GetChild(i).localScale = new Vector3(0.2f, 3f, 0.01f);
boxTransforms[i] = transform.GetChild(i);
meshRenderers[i] = transform.GetChild(i).GetComponent<MeshRenderer>();
}
}
public void SetScale()
{
for(int i=0;i<64;i++)
{
Vector3 _v3 = boxTransforms[i].transform.localScale;
float a = sepctrumData[i] * 100000;
Vector3 _v4 = new Vector3(0.2f, Mathf.Clamp(a, 0.1f, 3), 0.01f);
boxTransforms[i].localScale = Vector3.Lerp(boxTransforms[i].localScale, _v4, Time.deltaTime * UpLerp);
}
}
public void SetColor()
{
for (int i = 0; i < 64; i++)
{
if (boxTransforms[i].localScale.y <= 0.4f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.2f, 0.5f, 0.5f));
}
else if (boxTransforms[i].localScale.y <= 0.8f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.12f, 0.84f, 0.38f));
}
else if (boxTransforms[i].localScale.y <= 1.2f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.12f, 0.84f, 0.38f));
}
else if (boxTransforms[i].localScale.y <= 1.6f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.23f, 0.89f, 0.05f));
}
else if (boxTransforms[i].localScale.y <= 2f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.63f, 0.56f, 0.04f));
}
else if (boxTransforms[i].localScale.y <= 2.4f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.92f, 0.27f, 0.02f));
}
else if (boxTransforms[i].localScale.y <= 2.8f)
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.92f, 0.27f, 0.02f));
}
else
{
meshRenderers[i].material.SetColor("_EmissionColor", new Color(0.90f, 0.01f, 0.1f));
}
}
}
}
Spawn
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawn : MonoBehaviour
{
public List<Box> boxList;
public List<Transform> transfromList;
public float boxSpeed;
public GameObject boomPrefab;
public void Init()
{
boxSpeed = 5;
}
private void Start()
{
Init();
}
public void CreateBox()
{
GameObject temp = GameObject.Instantiate(boxList[Random.Range(0, boxList.Count)]).gameObject;
temp.transform.position = transfromList[Random.Range(0, transfromList.Count)].position;
Box box = temp.GetComponent<Box>();
BoxType type = BoxType.Up;
int num = Random.Range(0, 4);
switch (num)
{
case 0:
type = BoxType.Up; break;
case 1:
type = BoxType.Left; break;
case 2:
type = BoxType.Down; break;
case 3:
type = BoxType.Right; break;
}
box.Init(boxSpeed, type);
box.SetRotationBaseType();
}
public void CreateBoom()
{
GameObject temp = GameObject.Instantiate(boomPrefab);
temp.transform.position= transfromList[Random.Range(0, transfromList.Count)].position;
Boom boom=temp.GetComponent<Boom>();
boom.Init(boxSpeed);
}
}
SortPannel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SortPannel : MonoBehaviour
{
public Text sortText;
private void Start()
{
sortText = GetComponentInChildren<Text>();
ShowInfo();
}
public void ShowInfo()
{
DataMgr.Instance.ReadDate();
if(DataMgr.Instance.saveScore.Count==0)
{
sortText.text = "_";
}
else
{
DataMgr.Instance.saveScore.Sort((x, y) => -x.CompareTo(y));
sortText.text = "BestScore:" + DataMgr.Instance.saveScore[0];
}
}
}
Slice
using EzySlice;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.IO;
using UnityEngine;
using Valve.VR;
public class Slice : MonoBehaviour
{
public GameObject source;
public Material material;
public AudioSource audioSource;
public AudioClip clip;
public Saber saber;
public int saberID;
public GameObject hitEffect;
private void Start()
{
audioSource=GetComponent<AudioSource>();
saberID = saber.saberColor;
}
public void OnTriggerEnter(Collider other)
{
if(other.tag!="Box")
{
return;
}
source = other.gameObject;
SlicedHull slicedHull = source.Slice(transform.position, transform.right,material);
if(source==null)
{
return;
}
if(slicedHull==null)
{
return;
}
audioSource.PlayOneShot(clip);
Shake();
GameObject temp = GameObject.Instantiate(hitEffect, transform.position, Quaternion.identity);
GameObject.Destroy(temp, 0.5f);
if(saber.saberColor==other.gameObject.transform.root.GetComponent<Box>().boxColor)
{
//
GameMgr.Instance.UpdateScore(1);
GameMgr.Instance.UpdateCombom();
GameMgr.Instance.lv.AddLV();
}
GameObject upGo = slicedHull.CreateUpperHull(source,material);
GameObject lowerGo = slicedHull.CreateLowerHull(source, material);
Vector3 location = this.transform.position;
Vector3 closetPosition = other.ClosestPoint(location);
upGo.transform.position = closetPosition;
lowerGo.transform.position = closetPosition;
GameObject.Destroy(other.transform.parent.gameObject);
upGo.AddComponent<Rigidbody>();
lowerGo.AddComponent<Rigidbody>();
upGo.GetComponent<Rigidbody>().AddExplosionForce(500, upGo.transform.position - transform.right, 3);
lowerGo.GetComponent<Rigidbody>().AddExplosionForce(500, lowerGo.transform.position + transform.right, 3);
GameObject.Destroy(upGo.gameObject, 0.5f);
GameObject.Destroy(lowerGo.gameObject, 0.5f);
}
public void Shake()
{
SteamVR_Actions.default_Haptic.Execute(0, 0.5f, 100, 200,saber.pose.inputSource);
}
}
Player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR.Extras;
public class Player : MonoBehaviour
{
public GameObject swordRed;
public GameObject swordBlue;
public GameObject ControllerLeft;
public GameObject ControllerRight;
public InteractUI interactLeft;
public InteractUI interactRight;
public void Awake()
{
interactLeft = ControllerLeft.GetComponent<InteractUI>();
interactRight = ControllerLeft.GetComponent<InteractUI>();
}
public void ShowOrHideSaber(bool isShow)
{
swordRed.gameObject.SetActive(isShow);
swordBlue.gameObject.SetActive(isShow);
}
}
MusicEvent
using SonicBloom.Koreo;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class MusicEvent : MonoBehaviour
{
public string eventCreate;
public Spawn spawn;
public string eventGameOver;
private void Start()
{
eventCreate = "Create";
Koreographer.Instance.RegisterForEvents(eventCreate, Create);
spawn = GameObject.Find("Spawn").GetComponent<Spawn>();
eventGameOver = "SongOver";
Koreographer.Instance.RegisterForEvents(eventGameOver, SongOver);
}
private void SongOver(KoreographyEvent koreoEvent)
{
GameMgr.Instance.gameState = GameState.gameEnd;
}
private void Create(KoreographyEvent koreoEvent)
{
int num =Random.Range(0, 10);
if(num<=8)
{
spawn.CreateBox();
}
else
{
spawn.CreateBoom();
}
}
}
GameMgr
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum GameState
{
gamePrepare,
gameStart,
gameEnd,
}
public class GameMgr : MonoBehaviour
{
private static GameMgr instance;
public static GameMgr Instance
{
get
{
if (instance != null)
{
return instance;
}
else
{
//为了防止脚本还未挂到物体上,找不到的异常情况,可以自行创建空物体挂上去
instance = Object.FindFirstObjectByType<GameMgr>();
if (instance == null)
{
//如果创建对象,则会在创建时调用其身上脚本的Awake
//所以此时无需为instance赋值,其会在Awake中赋值,自然也会初始化所以无需init()
GameObject go = new GameObject("GameMgr");
go.AddComponent<GameMgr>();
}
instance.Init();
}
return instance;
}
}
public int currentCombo;
public int currentScore;
public ScorePannel scorePannel;
public bool isInterrupt=false;
public int currentLV;
public LV lv;
public LVPannel lVPannel;
public Dictionary<int, AudioClip> songDic = new Dictionary<int, AudioClip>();
public AudioClip clip1;
public AudioClip clip2;
public AudioSource audioSource;
public GameState gameState;
public GameObject musicPlayer;
public DataMgr datamgr;
public MainPannel mainPannel;
public Player player;
private void Awake()
{
instance = this;
scorePannel=GameObject.Find("ScoreBg").GetComponent<ScorePannel>();
lVPannel= GameObject.Find("LVBg").GetComponent<LVPannel>();
mainPannel= GameObject.Find("MainBg").GetComponent<MainPannel>();
musicPlayer = GameObject.Find("MusicPlayer");
player = GameObject.Find("XR Origin").GetComponent<Player>();
Init();
}
public void Init()
{
gameState = GameState.gamePrepare;
songDic.Clear();
songDic.Add(1, clip1);
songDic.Add(2,clip2);
currentCombo = 0;
currentLV = 0;
currentScore = 0;
isInterrupt = false;
}
private void Start()
{
Prepare();
}
public void UpdateScore(int score)
{
currentScore += score;
if(currentScore<=0)
{
currentScore = 0;
}
scorePannel.UpdateScore(currentScore);
}
public void UpdateCombom()
{
if(isInterrupt)
{
currentCombo = 0;
scorePannel.UpdateCombo(0);
isInterrupt = false;
}
else
{
currentCombo++;
scorePannel.UpdateCombo(currentCombo);
}
}
public AudioClip SetSong(int index)
{
AudioClip clip;
songDic.TryGetValue(index, out clip);
if(clip==null)
{
clip = clip1;
}
return clip;
}
public void Prepare()
{
AudioClip clip = SetSong(DataMgr.Instance.currentIndex);
audioSource.clip = clip;
audioSource.Play();
player.ShowOrHideSaber(true);
mainPannel.gameObject.SetActive(false);
scorePannel.Init();
lVPannel.Init();
gameState = GameState.gameStart;
}
private void Update()
{
if (gameState==GameState.gameEnd)
{
GameOver();
}
}
public void GameOver()
{
mainPannel.gameObject.SetActive(true);
mainPannel.ShowScore(currentScore);
audioSource.Stop();
player.ShowOrHideSaber(false);
}
}
MainPannel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class MainPannel : MonoBehaviour
{
public Text totalText;
public Button btn_Restart;
public Button btn_Back;
private void Awake()
{
totalText=transform.Find("Text_Total").GetComponentInChildren<Text>();
btn_Back=transform.Find("Btn_Back").GetComponentInChildren<Button>();
btn_Restart=transform.Find("Btn_Restart").GetComponentInChildren<Button>();
btn_Back.onClick.AddListener(() => { Back(); });
btn_Restart.onClick.AddListener(() => { Restart(); });
}
public void Back()
{
//
DataMgr.Instance.currentScore = GameMgr.Instance.currentScore;
//
DataMgr.Instance.WriteData(DataMgr.Instance.currentScore);
SceneManager.LoadScene(0);
}
public void Restart()
{
GameMgr.Instance.Init();
GameMgr.Instance.Prepare();
}
public void ShowScore(int score)
{
totalText.text = "Score:" + score;
}
}
LVPannel
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LVPannel : MonoBehaviour
{
public Text textLV;
public Text healthText;
public int maxHealth;
public int currentHealth;
private void Awake()
{
textLV= transform.Find("Text_LV").GetComponent<Text>();
healthText = transform.Find("Text_Health").GetComponent<Text>();
maxHealth = currentHealth = 100;
}
public void Init()
{
textLV.text = "LV:1";
healthText.text = "Health:100";
}
private void Start()
{
Init();
}
public void CalculateDamage(int lv)
{
int baseCount = 10;
float damage = maxHealth / (baseCount * 1.5f + lv - 1);
int damage1 = Convert.ToInt32(damage);
currentHealth -= damage1;
if(currentHealth<=0)
{
currentHealth = 0;
}
healthText.text = "Health:" + currentHealth;
}
public void UpdateLV(int lv)
{
textLV.text = "LV:" + lv;
}
}
LV
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LV : MonoBehaviour
{
public int nextLevelScore;
public Dictionary<int, int> lvScoreDic = new Dictionary<int, int>();
void Awake()
{
Init();
}
private void Init()
{
lvScoreDic.Clear();
lvScoreDic.Add(1, 3);
lvScoreDic.Add(2, 5);
lvScoreDic.Add(3, 7);
lvScoreDic.Add(4, 10);
lvScoreDic.Add(5, 14);
lvScoreDic.Add(6, 18);
lvScoreDic.Add(7, 25);
}
public void LimitLV()
{
if (GameMgr.Instance.currentLV <= 1)
{
GameMgr.Instance.currentLV = 1;
}
if (GameMgr.Instance.currentLV >= 8)
{
GameMgr.Instance.currentLV = 8;
}
}
public void CalculateLV()
{
if (GameMgr.Instance.currentLV >= 1 && GameMgr.Instance.currentLV <= 7)
{
nextLevelScore = lvScoreDic[GameMgr.Instance.currentLV];
}
}
public void AddLV()
{
CalculateLV();
if (GameMgr.Instance.currentScore >= nextLevelScore)
{
GameMgr.Instance.currentLV += 1;
LimitLV();
GameMgr.Instance.lVPannel.UpdateLV(GameMgr.Instance.currentLV);
}
}
public void ReduceLV()
{
GameMgr.Instance.currentLV -= 1;
LimitLV();
GameMgr.Instance.lVPannel.UpdateLV(GameMgr.Instance.currentLV);
}
}
CheckMiss
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CheckMiss : MonoBehaviour
{
public void OnTriggerEnter(Collider other)
{
if(other.tag=="Box")
{
GameMgr.Instance.isInterrupt = true;
GameMgr.Instance.UpdateCombom();
}
GameObject.Destroy(other.gameObject);
}
}
Box
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BoxType
{
Up,
Down,
Left,
Right,
}
public class Box : MonoBehaviour
{
public float boxSpeed;
public BoxType boxType;
public int boxColor;
private void Start()
{
GameObject.Destroy(this.gameObject, 8f);
}
public void Init(float speed,BoxType type)
{
boxSpeed = speed;
boxType = type;
}
public void SetRotationBaseType()
{
switch(boxType)
{
case BoxType.Up:
transform.rotation = Quaternion.Euler(0, 0, 0);
break;
case BoxType.Left:
transform.rotation = Quaternion.Euler(0, 0, 90);
break;
case BoxType.Down:
transform.rotation = Quaternion.Euler(0, 0, 180);
break;
case BoxType.Right:
transform.rotation = Quaternion.Euler(0, 0, 270); ;
break;
}
}
public void Update()
{
transform.Translate(-transform.forward * Time.deltaTime * boxSpeed);
if(GameMgr.Instance.gameState==GameState.gameEnd)
{
GameObject.Destroy(this.gameObject);
}
}
}
Boom
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Boom : MonoBehaviour
{
public float Speed;
public GameObject hitEffect;
private void Start()
{
GameObject.Destroy(this.gameObject, 8f);
}
public void Init(float speed=5)
{
Speed = speed;
}
public void Update()
{
transform.Translate(-transform.forward * Time.deltaTime *Speed);
if (GameMgr.Instance.gameState == GameState.gameEnd)
{
GameObject.Destroy(this.gameObject);
}
}
public void OnTriggerEnter(Collider other)
{
if(other.tag=="Slice")
{
GameMgr.Instance.lv.ReduceLV();
GameMgr.Instance.lVPannel.CalculateDamage(GameMgr.Instance.currentLV);
GameMgr.Instance.UpdateScore(-2);
GameObject go= GameObject.Instantiate(hitEffect, transform.position, Quaternion.identity);
GameObject.Destroy(go, 0.5f);
GameObject.Destroy(gameObject);
}
}
}
StartUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//给按钮点击注册事件 选中哪个歌,就记录该首歌 ,跳转目标场景
public class StartUI : MonoBehaviour
{
public List<SongSlot> btnSongList;
private void Start()
{
SetSlotUI();
}
public void SetSlotUI()
{
for (int i = 0; i < btnSongList.Count; i++)
{
//注数组越界 完整的应写无限滚动列表
//注意i 可能在字典里越界
btnSongList[i].slotIndex = i;
btnSongList[i].SetUI(DataMgr.Instance.songNameDic[i]);
}
}
}
SongSlot
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SongSlot : MonoBehaviour
{
public Text song;
public string songName;
//格子索引
public int slotIndex;
private void Awake()
{
song = GetComponentInChildren<Text>();
GetComponent<Button>().onClick.AddListener(() => { LoadGame(); });
}
//设置UI信息 安全校验
public void SetUI(string name)
{
if (string.IsNullOrEmpty(name))
{
return;
}
songName = name;
song.text = songName;
}
//如果当前格子没有显示歌曲名 不跳转场景
public void LoadGame()
{
if (string.IsNullOrEmpty(song.text))
{
return;
}
SceneManager.LoadScene(1);
}
}
InteractUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Valve.VR.Extras;
[RequireComponent(typeof(SteamVR_LaserPointer))]
public class InteractUI : MonoBehaviour
{
private SteamVR_LaserPointer laser;
void Start()
{
laser = GetComponent<SteamVR_LaserPointer>();
laser.PointerClick += Laser_PointerClick;
laser.PointerIn += Laser_PointerIn;
laser.PointerOut += Laser_PointerOut;
}
private void Laser_PointerOut(object sender, PointerEventArgs e)
{
}
private void Laser_PointerIn(object sender, PointerEventArgs e)
{
}
private void Laser_PointerClick(object sender, PointerEventArgs e)
{
Button btn = e.target.GetComponent<Button>();
if(btn!=null)
{
SongSlot slot= btn.GetComponentInChildren<SongSlot>();
if(slot!=null)
{
DataMgr.Instance.currentIndex = slot.slotIndex;
}
btn.onClick.Invoke();
}
}
void Update()
{
}
}
DataMgr
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
//数据管理类 单例
public class DataMgr : MonoBehaviour
{
private static DataMgr instance;
//歌曲名字典
public Dictionary<int, string> songNameDic = new Dictionary<int, string>();
public static DataMgr Instance
{
get
{
if (instance != null)
{
return instance;
}
else
{
//为了防止脚本还未挂到物体上,找不到的异常情况,可以自行创建空物体挂上去
instance = Object.FindFirstObjectByType<DataMgr>();
if (instance == null)
{
//如果创建对象,则会在创建时调用其身上脚本的Awake
//所以此时无需为instance赋值,其会在Awake中赋值,自然也会初始化所以无需init()
GameObject go = new GameObject("DataMgr");
go.AddComponent<DataMgr>();
}
instance.Init();
}
return instance;
}
}
public int currentIndex;
public int currentScore;
public string dataPath;
public List<int> saveScore=new List<int>();
private void Awake()
{
if(instance!=null)
{
GameObject.Destroy(this.gameObject);
return;
}
else
{
instance = this;
}
Init();
DontDestroyOnLoad(gameObject);
dataPath = Application.persistentDataPath + "/SaveScore.txt";
CreateDataFile();
}
private void Start()
{
}
public void Init()
{
//假数据
songNameDic.Clear();
songNameDic.Add(0, "Night");
songNameDic.Add(1, "");
songNameDic.Add(2, "");
songNameDic.Add(3, "");
}
public void CreateDataFile()
{
Debug.Log(dataPath);
if(!File.Exists(dataPath))
{
Debug.Log("不存在该文件");
File.Create(dataPath);
Debug.Log("该文件已创建");
return;
}
}
public void WriteData(int currentScore)
{
CreateDataFile();
using(StreamWriter sw = new StreamWriter(dataPath, true)) { sw.WriteLine(currentScore); }
}
public void ReadDate()
{
saveScore.Clear();
string str = string.Empty;
using(StreamReader sr = new StreamReader(dataPath))
{
while((str= sr.ReadLine()) != null)
{
if(string.IsNullOrWhiteSpace(str))
{
continue;
}
int score = int.Parse(str);
saveScore.Add(score);
}
}
}
}