Unity3D学习:飞碟游戏进化版
上一個做的飛碟游戲雖然是功能也齊全,但是我感覺架構不是很好有點紊亂,不利于后期維護以及改進,所以我按照一個完整的架構重新做了一次,思路更清晰,而且還添加了更多的功能。這次的飛碟游戲是兩個關卡,50分上第二關,100分通第二關,而且可以任意切換模式(運動學非剛體模式和物理剛體模式,前者沒有剛體組件,后者加剛體組件)
講講規則先:一開始就是第一關,默認模式為運動學非剛體模式,還是按空格發射飛碟(一次一個),一個發射期間不能發射第二個,一個飛碟如果沒打中會在一定時間內消失,飛碟消失才能發射下一個飛碟,鼠標左鍵射擊子彈,按數字鍵2切換模式為物理剛體模式,按數字鍵1切換到運動學非剛體模式。
上個效果圖(由于比較難射中,所以我把飛碟大小弄大一些,分數顯示被遮住了):
接下來講一下設計思路,游戲架構如下
DiskModule類掛在飛碟預設上,用來處理觸發器事件(飛碟碰到子彈或者地板時觸發)
DiskFactory類專門生產飛碟,所有生產飛碟的細節都在這里實現,會根據每個關卡生產不同大小以及顏色的飛碟,并且回收飛碟以便再次加以利用
Recorder類只負責記錄分數或者重置分數
Userface類處理用戶界面邏輯
CCActionManager類實現運動學的動作,比如運動學非剛體的飛碟發射
PhysicsActionManager類實現物理剛體學動作,比如子彈的發射以及剛體飛碟的發射
SceneController類加載場景以及調用各個其他類來實現功能,比如Userface調用子彈或者飛碟射擊要通過SceneController根據不同模式以及關卡來調用相應的動作管理器
具體代碼如下,(注釋已經把代碼思想寫的很清楚):
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Director : System.Object {private static Director _instance;public SceneController _Controller { get; set; }public static Director getinstance(){if (_instance == null){_instance = new Director();}return _instance;}public int getFPS(){return Application.targetFrameRate;}public void setFPS(int fps){Application.targetFrameRate = fps;} }using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Userface : MonoBehaviour {private SceneController _Controller;public Camera _camera;public Text Score;//顯示分數public Text Round;//顯示關卡public Text Mode;//顯示模式void Start () {_Controller = (SceneController)FindObjectOfType(typeof(SceneController));}// Update is called once per framevoid Update () {if(Input.GetKeyDown("1"))//按下1切換到運動學模式{if(!_Controller.isFlying){Debug.Log("NonPhy mode");_Controller._mode = false;}}if(Input.GetKeyDown("2"))//按下2切換到物理剛體模式{if (!_Controller.isFlying){Debug.Log("Phy mode");_Controller._mode = true;}}if(Input.GetKeyDown("space"))//按下空格發射飛碟{_Controller.ShootDisk();}if (Input.GetMouseButtonDown(0)&&!_Controller.isShooting)//按下左鍵發射子彈{Ray mouseRay = _camera.ScreenPointToRay(Input.mousePosition);_Controller.ShootBullet(mouseRay.direction);}Score.text = "Score:" + _Controller.getRecorder().getScore();Round.text = "Round:" + _Controller.getRound();if (_Controller._mode == false) Mode.text = "Mode:CCAction";else Mode.text = "Mode:PhysicsAction";} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Recorder : MonoBehaviour {private int _score = 0;public void AddScore(string name)//根據碰撞物名稱加減分{if (name == "Plane") _score -= 10;else if (name == "bullet(Clone)") _score += 10;}public int getScore(){return _score;}public void reset(){_score = 0;} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class DiskFactory : MonoBehaviour {public List<GameObject> Using; //儲存正在使用的public List<GameObject> Used; //儲存空閑的 private SceneController _Controller;public GameObject DiskPrefab;void Start () {Using = new List<GameObject>();Used = new List<GameObject>();_Controller = (SceneController)FindObjectOfType(typeof(SceneController));}public GameObject getDisk(bool isPhy,int _Round){GameObject t;if (Used.Count == 0){t = GameObject.Instantiate(DiskPrefab) as GameObject;}else{t = Used[0];Used.Remove(t);}t.GetComponent<MeshCollider>().isTrigger = true;t.SetActive(true);if (isPhy)//物理學模式加剛體組件{if (t.GetComponent<Rigidbody>() == null)t.AddComponent<Rigidbody>();}else if (!isPhy)//運動學模式去除剛體組件{if (t.GetComponent<Rigidbody>())Destroy(t.GetComponent<Rigidbody>());}Using.Add(t);if(_Round==1)//第一關的飛碟形式{t.transform.localScale *= 2;t.GetComponent<Renderer>().material.color = Color.green;}//第二關為初始大小以及紅色return t;}private void freeDisk(int round)//把場景中inactive的飛碟回收{for (int i = 0; i < Using.Count; i++){GameObject t = Using[i];if (!t.activeInHierarchy){Using.RemoveAt(i);Used.Add(t);Destroy(t.GetComponent<Rigidbody>());if (round==1)t.transform.localScale /= 2;t.GetComponent<Renderer>().material.color = Color.red;}}}void Update () {freeDisk(_Controller.getRound());} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class DiskModule : MonoBehaviour {private string _sth = "";private float _time = 8f;private SceneController _Controller;void Start () {_Controller = (SceneController)FindObjectOfType(typeof(SceneController));}void OnTriggerEnter(Collider other)//觸發器事件{if(_sth==""){_sth = other.gameObject.name;Debug.Log(_sth);if (_sth == "bullet(Clone)"){this._time = 0;//直接回收_Controller._explosion.GetComponent<Renderer>().material.color = this.GetComponent<Renderer>().material.color;_Controller._explosion.transform.position = this.transform.position;_Controller._explosion.Play();//播放爆炸粒子}_Controller.getRecorder().AddScore(_sth);_Controller.isShooting = false;}}void Update () {if (_Controller.isFlying){if (_time > 0) _time -= Time.deltaTime;else if (_time <= 0)//回收飛碟{GetComponent<MeshCollider>().isTrigger = false;this.gameObject.SetActive(false);_time = 8f;_sth = "";_Controller.isFlying = false;}}} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class SceneController : MonoBehaviour {private CCActionManager _CCAM;private PhysicsActionManager _PhyAM;private DiskFactory _Factory;private Recorder _Recorder;private int _Round = 1;public GameObject _bullet;//子彈public ParticleSystem _explosion;//爆炸粒子public bool _mode = false;//標記模式public bool isShooting = false;//判斷子彈是否正在飛public bool isFlying = false;//判斷飛碟是否正在飛private float _time = 1f;void Start () {_bullet = GameObject.Instantiate(_bullet) as GameObject;_explosion = GameObject.Instantiate(_explosion) as ParticleSystem;Director _director = Director.getinstance();_director._Controller = this;_CCAM = (CCActionManager)FindObjectOfType(typeof(CCActionManager));_PhyAM = (PhysicsActionManager)FindObjectOfType(typeof(PhysicsActionManager));_Recorder = (Recorder)FindObjectOfType(typeof(Recorder));_Factory = (DiskFactory)FindObjectOfType(typeof(DiskFactory));_director.setFPS(60);_director._Controller = this;}public DiskFactory getFactory(){return _Factory;}public int getRound(){return _Round;}public Recorder getRecorder(){return _Recorder;}public CCActionManager getCCActionManager(){return _CCAM;}public PhysicsActionManager getPhysicsActionManager(){return _PhyAM;}public void ShootDisk(){if(!isFlying){GameObject _disk = _Factory.getDisk(_mode, _Round);//根據不同關卡以及不同模式生產不同的飛碟if (!_mode) _CCAM.ShootDisks(_disk);//根據不同模式調用不同動作管理器的動作函數else _PhyAM.ShootDisks(_disk);isFlying = true;}}public void ShootBullet(Vector3 _dir)//調用動作管理器的射擊子彈函數{isShooting = true;_PhyAM.ShootBullets(_bullet, _dir);}private void AddRound()//判斷是否通關{if (_Recorder.getScore() >= 50&&_Round == 1){_Round++;}else if (_Recorder.getScore() > 100&& _Round == 2){_Round = 1;_Recorder.reset();}}void Update () {AddRound();if(isShooting){if(_time>0){_time -= Time.deltaTime;if(_time<=0){isShooting = false;_time = 1f;}}}} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class PhysicsActionManager : MonoBehaviour {private SceneController _Controller;void Start () {_Controller = (SceneController)FindObjectOfType(typeof(SceneController));}public void ShootBullets(GameObject _bullet, Vector3 _dir)//發射子彈{_bullet.transform.position = new Vector3(0, 2, 0);_bullet.GetComponent<Rigidbody>().velocity = Vector3.zero; // 子彈剛體速度重置_bullet.GetComponent<Rigidbody>().AddForce(_dir * 500f, ForceMode.Impulse);}public void ShootDisks(GameObject _disk)//發射飛碟{_disk.transform.position = new Vector3(0, 2, 2);float _dx = Random.Range(-20f, 20f);Vector3 _dir = new Vector3(_dx, 30, 20);_disk.transform.up = _dir;if (_Controller.getRound() == 1){_disk.GetComponent<Rigidbody>().AddForce(_dir*20f, ForceMode.Force);} else if(_Controller.getRound() == 2){_disk.GetComponent<Rigidbody>().AddForce(_dir*30f, ForceMode.Force);}}void Update () {} }
using System.Collections; using System.Collections.Generic; using UnityEngine;public class CCActionManager : MonoBehaviour {private SceneController _Controller;private GameObject temp;void Start () {_Controller = (SceneController)FindObjectOfType(typeof(SceneController));}public void ShootDisks(GameObject _disk)//發射飛碟{_disk.transform.position = new Vector3(Random.Range(-1f, 1f), 2f, 2f);temp = _disk;}void Update () {if(_Controller.isFlying&&!_Controller._mode){if (_Controller.getRound() == 1){temp.transform.position = Vector3.MoveTowards(temp.transform.position, new Vector3(0, 2, 100), 0.1f);}else if (_Controller.getRound() == 2){temp.transform.position = Vector3.MoveTowards(temp.transform.position, new Vector3(0, 2, 100), 0.2f);}}} }
總結
以上是生活随笔為你收集整理的Unity3D学习:飞碟游戏进化版的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HW5-打飞碟
- 下一篇: 交互入门——基于鼠标控制的射击飞碟小游戏