Unity3d實現滑鼠打飛碟(Hit UFO)遊戲
要求
1、編寫一個簡單的滑鼠打飛碟(Hit UFO)遊戲
- 遊戲內容要求:
- 遊戲有 n 個 round,每個 round 都包括10 次 trial;
- 每個 trial 的飛碟的色彩、大小、發射位置、速度、角度、同時出現的個數都可能不同。它們由該 round 的 ruler 控制;
- 每個 trial 的飛碟有隨機性,總體難度隨 round 上升;
- 滑鼠點中得分,得分規則按色彩、大小、速度不同計算,規則可自由設定。
- 遊戲的要求:
- 使用帶快取的工廠模式管理不同飛碟的生產與回收,該工廠必須是場景單例項的!具體實現見參考資源 Singleton 模板類
- 近可能使用前面 MVC 結構實現人機互動與遊戲模型分離
如果你的使用工廠有疑問,參考:彈藥和敵人:減少,重用和再利用;參考:Unity物件池(Object Pooling)理解與簡單應用程式碼質量較低,比較凌亂
具體程式碼請參考我的gitee
https://gitee.com/woodx9/unity-3D-homework/tree/master/HItUFO
執行效果圖
完整圖(上面沒有把分數GUI錄入)
因為熟練運用了上次牧師與魔鬼的框架,所以僅僅用一天時間就把打飛碟做出來了
設計:
1. 飛碟自身會旋轉,加上附加的圖片有漂亮的星星,所以有風火輪的既視感
2. 飛碟的總數量是20個,打死它們後,飛碟會重生
3. 當滑鼠打掉飛碟後,飛碟會往下掉,而且玩家會獲得加分,分數為飛碟到攝像頭的距離
4. 飛碟的執行軌跡,它們的軌跡一定會經過,Z為50,25, 10,5的垂直與Z平面的隨機點(這個隨機點大概率在攝像頭視野內)
5.隨著分數的升高,飛碟的速度會越來越快
部署:
攝像頭掛載
飛碟掛載
程式碼淺析:
飛碟運動 程式碼在CCActionManager.cs
public void UFOToDestination(int num) { GameObject obj = sceneController.goList[num]; obj.transform.position = new Vector3(Random.Range(-1 * 100 / 2, 100 / 2), Random.Range(-1 * 100 / 2, 100 / 2), 100); CCSequenceAction css = CCSequenceAction.GetSSAction(1, 0, new List<SSAction> {shakeTheDestination(50), shakeTheDestination(25), shakeTheDestination(10), shakeTheDestination(5)}); //改變 goList_usedAndFree[i] = 1; sceneController.goList_usedAndFree[num] = 1; this.RunAction(obj, css, this); } public CCMoveToAction shakeTheDestination(int positionZ) { return CCMoveToAction.GetSSAction(new Vector3(Random.Range(-1 * positionZ/2 , positionZ/2), Random.Range(-1* positionZ/2, positionZ/2), positionZ), SSDirector.getInstance().GetCreditCount() / 300 + 10); }
輸入num是指定飛碟的序號,然後會給飛碟指定一連串隨機的目的地
// UFO墜落 public void UFODrop(int num) { GameObject obj = sceneController.goList[num]; CCMoveToAction ccma = CCMoveToAction.GetSSAction(new Vector3(obj.transform.position.x, -100, obj.transform.position.z), 50); this.RunAction(obj, ccma, this); }
如果飛碟被點選,會給飛碟指定向下掉的運動
//隱藏UFO public void hideUFO(int num) { GameObject go = sceneController.goList[num]; go.transform.position = new Vector3(0, 0, -5); }
隱藏UFO,當飛碟不用時,可以把它藏在攝像頭的後面
檢測點選函式 PickUpObject.cs 掛載在攝像頭上
using System.Collections; using System.Collections.Generic; using System.Diagnostics; using UnityEngine; public class PickupObject : MonoBehaviour { public GameObject cam; // Update is called once per frame void Update() { if (Input.GetButtonDown("Fire1")) { Vector3 mp = Input.mousePosition; //get Screen Position //create ray, origin is camera, and direction to mousepoint Camera ca; if (cam != null) ca = cam.GetComponent<Camera>(); else ca = Camera.main; Ray ray = ca.ScreenPointToRay(Input.mousePosition); //Return the ray's hit RaycastHit hit; if (Physics.Raycast(ray, out hit)) { //如果遊戲結束了就不能點選了 if (SSDirector.getInstance().gameEnd) return; if (hit.collider.gameObject.tag.Contains("Finish")) { //plane tag } GameObject parentGameObject = hit.transform.parent.gameObject; SSDirector ssdDirector = SSDirector.getInstance(); // Debug.Log(parentGameObject.GetComponent<UFOController>().getNum()); 不能用這個確定UFO的index,原因未知 // 計算得分 按距離相機位置算分數 int credit = (int)Vector3.Distance(parentGameObject.transform.position, new Vector3(0, 1, 0)); ssdDirector.AddCreditCount(credit); ssdDirector.ccam.UFODrop(ssdDirector.firstcontroller.getGameObjectIndex(parentGameObject.transform.position)); } } } }
如果檢測到點選,就計算得分,然後傳給SSDirector函式
然後指定UFO執行墜落函式
那麼如果UFO墜落之後,如何檢測到它墜落了並且回收呢?
在SSActionManager.cs中
foreach (int key in waitingDelete) { SSAction ac = actions[key]; // 檢查是不是掉落的UFO,如果是的話Y軸高度低於-90,然後檢查actions中是否還有掉落UFO的運動,有的話就刪除它們的運動,然後把它們移動到隱藏位置 // 如果不是掉落的UFO,則說明UFO已經到達指定位置,突圍成功,遊戲結束 if (ac.transform.position.y < -50) { foreach (KeyValuePair<int, SSAction> kv in actions) { SSAction t_ac = kv.Value; if (t_ac != ac && ac.gameobject == t_ac.gameobject) { t_ac.destory = true; //隱藏 SSDirector ssdDirector = SSDirector.getInstance(); ssdDirector.ccam.hideUFO(ssdDirector.firstcontroller.getGameObjectIndex(ac.transform.position)); ssdDirector.firstcontroller.goList_usedAndFree[ssdDirector.firstcontroller.getGameObjectIndex(ac.transform.position)] = 0; } } } //到達了最終位置 else if (ac.transform.position.z <= 10) { //code SSDirector ssdDirector = SSDirector.getInstance(); ssdDirector.gameEnd = true; } actions.Remove(key); Destroy(ac); }
當檢測到飛碟墜落後,它還有一個運動還在執行,即原先設定的運動軌跡,因此要找到並刪除它。
如果有飛碟到了最終的位置,則通知SSDirector,結束遊戲
在FirstController.cs中,有一個變數
public List<int> goList_usedAndFree; //0代表飛碟空閒,1代表飛碟忙碌
這樣就可以檢測,飛碟是否在忙碌,如果不忙碌的話,就可以重生
// Update is called once per frame void Update() { for (int i = 0; i < goList_usedAndFree.Count; ++i) { if (goList_usedAndFree[i] == 0) { SSDirector.getInstance().ccam.UFOToDestination(i); } } }