Unity 3D-learning 打飞碟游戏改进版ben
一、改進打飛碟游戲
- 游戲內容要求:
- 按?adapter模式?設計圖修改飛碟游戲
- 使它同時支持物理運動與運動學(變換)運動
- adapter模式設計簡要展示:
SceneController?類,作為 Adaptee,實現了最初的方法。
IUserInterface、IQueryStatus、IJudgeEvent作為接口,定義了客戶端調用的方法,作為Target。
SceneControllerBC類繼承了SceneController類,作為Adpter。
二、具體實現
下面開始介紹游戲制作過程。
相比此前的牧師與魔鬼游戲,飛碟游戲里需要考慮的預設對象很少,只需要制作一個飛碟對象以及一個子彈對象。為了簡化外形,我們設定飛盤為圓柱體,子彈為球體,具體的尺寸設置如下。
在子彈打擊到飛碟時,考慮到飛碟 的摧毀效果,我們可以添加一個粒子系統名為explosion
與此同時,我們還需要顯示出游戲的輪數和當前得分,所以我們需要設置 UI的Text控件
除此之外,最好有一個游戲說明,于是我們設計一個按鈕,當按鈕被按下時,會顯示游戲說明
這個按鈕并不在Hierarchy中設計,而是在IUserInterface類中的OnGUI函數中完成實現。
物理學屬性剛體,可以更好的模擬物體的運動。以下是為飛盤、子彈對象添加剛體屬性的截圖:?
工廠模式并畫出UML圖
并按照UML圖實現代碼。
SceneControllerBC類的實現:
SceneController
using UnityEngine; using System.Collections; using Mygame; namespace Mygame { public interface IUserInterface { void emitDisk(); } public interface IQueryStatus { bool isCounting(); bool isShooting(); int getRound(); int getScore(); int getEmitTime(); } public interface IJudgeEvent { void nextRound(); void setScore(int Score); } public class SceneController : System.Object, IQueryStatus, IUserInterface, IJudgeEvent { private static SceneController instance; private SceneControllerBC baseCode; private GameModel gameModel; private Judge judge; private int round; private int score; public static SceneController getInstance() { if (instance == null) { instance = new SceneController(); } return instance; } public void setGameModel(GameModel obj) { gameModel = obj;} internal GameModel getGameModel() { return gameModel;} public void setJudge(Judge obj) { judge = obj;} internal Judge getJudge() { return judge;} public void setSceneControllerBC(SceneControllerBC obj) { baseCode = obj;} internal SceneControllerBC getSceneControllerBC() {return baseCode;} public void emitDisk() { gameModel.prepareToEmitDisk();} public bool isCounting() { return gameModel.isCounting();} public bool isShooting() { return gameModel.isShooting();} public int getRound() { return round; } public int getScore() { return score;} public int getEmitTime() { return (int)gameModel.timeToEmit + 1;} public void setScore(int score_) { score = score_;} public void nextRound() { score = 0;baseCode.loadRoundData(++round);} } public class SceneControllerBC : MonoBehaviour { private Color color; private Vector3 emitPos; private Vector3 emitDir; private float speed; void Awake() { SceneController.getInstance().setSceneControllerBC(this); } public void loadRoundData(int round) { if (round == 1) {color = Color.green; emitPos = new Vector3(-2.5f, 0.2f, -5f); emitDir = new Vector3(24.5f, 40.0f, 67f); speed = 3; SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 1); }else if (round==2) {color = Color.red; emitPos = new Vector3(2.5f, 0.2f, -5f); emitDir = new Vector3(-24.5f, 35.0f, 67f); speed = 4; SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 2); }} } }DiskFactoryBC類的實現
1.DiskFactoryBC類的目的是管理飛碟實例,使用單例模式,得到飛碟id,得到飛碟對象,釋放飛碟對象,為了避免開銷大的問題,沒有用destory,而是設置為diskList[id].SetActive(false);
using UnityEngine; using System.Collections; using System.Collections.Generic; using Mygame; namespace Mygame { public class DiskFactory : System.Object { private static DiskFactory _instance; private static List<GameObject> diskList;public GameObject Disk; public static DiskFactory getInstance() { if (_instance == null) { _instance = new DiskFactory(); diskList = new List<GameObject>(); } return _instance; } public int getDisk() { for (int i = 0; i < diskList.Count; ++i) { if (!diskList[i].activeInHierarchy) { return i; } } diskList.Add(GameObject.Instantiate(Disk) as GameObject); return diskList.Count-1; } public GameObject getDiskObject(int id) { if (id > -1 && id < diskList.Count) { return diskList[id]; } return null; } public void free(int id) { if (id > -1 && id < diskList.Count) { diskList[id].GetComponent<Rigidbody>().velocity = Vector3.zero; diskList[id].transform.localScale = Disk.transform.localScale; diskList[id].SetActive(false); } } } } public class DiskFactoryBC : MonoBehaviour { public GameObject disk; void Awake () { DiskFactory.getInstance().Disk = disk; } }實現Judge類
1.控制得分系統,打中飛碟加分,錯過飛碟扣分,當分數累積到一定的程度自動進入下一關
using UnityEngine; using System.Collections; using Mygame; public class Judge : MonoBehaviour { public int oneDiskScore = 10; public int oneDiskFail = 10; public int disksToWin = 4; private SceneController scene; void Awake() { scene = SceneController.getInstance(); scene.setJudge(this); } void Start() { scene.nextRound(); } public void scoreADisk() { scene.setScore(scene.getScore() + oneDiskScore); if (scene.getScore() == disksToWin*oneDiskScore) { scene.nextRound(); } } public void failADisk() { scene.setScore(scene.getScore() - oneDiskFail); } }實現IUserInterface類
1.用戶界面,在此實現得分板,當前關卡的顯示以及設置一個RepeatButton可以顯示游戲規則;處理用戶的輸入,用戶輸入入有兩種:鼠標左鍵和空格。左鍵發射子彈,空格發射飛碟。
? ? ? ? 子彈射擊的思路:當用戶點擊鼠標時,從攝像機到鼠標創建一條射線,射線的方向即是子彈發射的方向,子彈采用剛體組件,因此發射子彈只需要給子彈施加一個力。子彈對象只有一個,下一次發射子彈時,必須改變子彈的位置。為了不讓子彈繼承上一次發射的速度,必須將子彈的速度歸零重置。采用射線而來判斷子彈是否擊中飛碟。? ? ?
using UnityEngine; using UnityEngine.UI; using System.Collections; using Mygame; public class UserInterface : MonoBehaviour { public Text mainText; public Text scoreText; public Text roundText; string ruleText = "按下空格鍵以發射飛碟,點擊鼠標左鍵發射子彈,每打中一個飛碟可得到10分,每錯過一個飛碟扣十分,累積到一定的分數可進入下一關。";private int round; public GameObject bullet; public ParticleSystem explosion; public float fireRate = .25f; public float speed = 500f; private float nextFireTime; private IUserInterface userInt; private IQueryStatus queryInt; void Start() { bullet = GameObject.Instantiate(bullet) as GameObject; explosion = GameObject.Instantiate(explosion) as ParticleSystem; userInt = SceneController.getInstance() as IUserInterface; queryInt = SceneController.getInstance() as IQueryStatus; } void Update () { if (queryInt.isCounting()) { mainText.text = ((int)queryInt.getEmitTime()).ToString(); } else { if (Input.GetKeyDown("space")) { userInt.emitDisk(); } if (queryInt.isShooting()) { mainText.text = ""; } if (queryInt.isShooting() && Input.GetMouseButtonDown(0) && Time.time > nextFireTime ) { nextFireTime = Time.time + fireRate; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); bullet.GetComponent<Rigidbody>().velocity = Vector3.zero; bullet.transform.position= transform.position; bullet.GetComponent<Rigidbody>().AddForce(ray.direction*speed, ForceMode.Impulse); RaycastHit hit; if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "Disk") { explosion.transform.position = hit.collider.gameObject.transform.position; explosion.GetComponent<Renderer>().material.color = hit.collider.gameObject.GetComponent<Renderer>().material.color; explosion.Play(); hit.collider.gameObject.SetActive(false); } } } roundText.text = "Round: " + queryInt.getRound().ToString(); scoreText.text = "Score: " + queryInt.getScore().ToString();if (round != queryInt.getRound()) { Debug.Log (round);round = queryInt.getRound(); mainText.text = "Round " + round.ToString() + " !"; Debug.Log (round);} } void OnGUI() {if (GUI.RepeatButton (new Rect (10, 10, 100, 40), "Help")) {GUI.TextArea(new Rect(10, 60, 750, 100),ruleText);}} }在完成了腳本的設計后,將五個腳本都掛載到攝像機上
并且將預制好的游戲對象分別拖入到相應的位置即可完成游戲的設計。
總結
以上是生活随笔為你收集整理的Unity 3D-learning 打飞碟游戏改进版ben的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3D游戏编程 作业五 枪打恶鬼(打飞碟)
- 下一篇: 【游戏开发】unity教程4 打飞碟小游