日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Unity3d--飞碟游戏

發(fā)布時(shí)間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity3d--飞碟游戏 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一.游戲規(guī)則與要求

  • 游戲內(nèi)容要求:

    游戲有 n 個(gè) round,每個(gè) round 都包括10 次 trial;
    每個(gè) trial 的飛碟的色彩、大小、發(fā)射位置、速度、角度、同時(shí)出現(xiàn)的個(gè)數(shù)都可能不同。它們由該 round 的 ruler 控制;
    每個(gè) trial 的飛碟有隨機(jī)性,總體難度隨 round 上升;
    鼠標(biāo)點(diǎn)中得分,得分規(guī)則按色彩、大小、速度不同計(jì)算,規(guī)則可自由設(shè)定。

  • 游戲的要求:

    使用帶緩存的工廠模式管理不同飛碟的生產(chǎn)與回收,該工廠必須是場(chǎng)景單實(shí)例的!具體實(shí)現(xiàn)見參考資源 Singleton 模板類
    近可能使用前面 MVC 結(jié)構(gòu)實(shí)現(xiàn)人機(jī)交互與游戲模型分離

二.游戲UML類圖

三.代碼說(shuō)明

首先是動(dòng)作控制器:前面大題的架構(gòu)與上次作業(yè)中的架構(gòu)基本相同,在場(chǎng)景控制器中使用FlyActionManager 類的函數(shù),然后在FlyActionManager 類中調(diào)頁(yè)UFOFlyAction類進(jìn)行每一幀對(duì)飛碟位置的更新即可實(shí)現(xiàn)飛碟飛的動(dòng)作。
在UFOFlyAction類中,給飛碟一個(gè)方向和一個(gè)力,然后飛碟每一幀計(jì)算下一幀做有向下加速度的飛行動(dòng)作的位置,然后進(jìn)行賦值即可實(shí)現(xiàn)的飛行動(dòng)作。
最后當(dāng)飛碟被點(diǎn)中或者飛出場(chǎng)景外就需要等待場(chǎng)景控制器和飛碟工廠進(jìn)行配合回收飛碟。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class SSAction : ScriptableObject {public bool enable = true; public bool destroy = false; public GameObject gameobject; public Transform transform; public ISSActionCallback callback; protected SSAction() { }public virtual void Start(){throw new System.NotImplementedException();}public virtual void Update(){throw new System.NotImplementedException();} }public enum SSActionEventType : int { Started, Competeted }public interface ISSActionCallback {void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null); }public class SSActionManager : MonoBehaviour, ISSActionCallback {private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>(); private List<SSAction> waitingAdd = new List<SSAction>(); private List<int> waitingDelete = new List<int>(); protected void Update(){foreach (SSAction ac in waitingAdd){actions[ac.GetInstanceID()] = ac; }waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> kv in actions){SSAction ac = kv.Value;if (ac.destroy) {waitingDelete.Add(ac.GetInstanceID());}else if (ac.enable){ac.Update();}}foreach (int key in waitingDelete){SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager){action.gameobject = gameobject;action.transform = gameobject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null){} } public class FlyActionManager : SSActionManager{public UFOFlyAction fly;public Controllor scene;protected void Start(){scene = (Controllor)SSDirector.GetInstance ().CurrentSceneControllor;scene.fam = this;}public void UFOfly(GameObject disk, float angle, float power){fly = UFOFlyAction.GetSSAction (disk.GetComponent<DiskData> ().direction, angle, power);this.RunAction (disk, fly, this);} } public class UFOFlyAction : SSAction {public float gravity = -5; private Vector3 start_vector; private Vector3 gravity_vector = Vector3.zero; private float time; private Vector3 current_angle = Vector3.zero; private UFOFlyAction() { }public static UFOFlyAction GetSSAction(Vector3 direction, float angle, float power){UFOFlyAction action = CreateInstance<UFOFlyAction>();if (direction.x == -1){action.start_vector = Quaternion.Euler(new Vector3(0, 0, -angle)) * Vector3.left * power;}else{action.start_vector = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right * power;}return action;}public override void Update(){time += Time.fixedDeltaTime;gravity_vector.y = gravity * time;transform.position += (start_vector + gravity_vector) * Time.fixedDeltaTime;current_angle.z = Mathf.Atan((start_vector.y + gravity_vector.y) / start_vector.x) * Mathf.Rad2Deg;transform.eulerAngles = current_angle;if (this.transform.position.y < -10){this.destroy = true;this.callback.SSActionEvent(this); }}public override void Start() { } }

接下來(lái)是飛碟工廠類:它實(shí)現(xiàn)了要求

使用帶緩存的工廠模式管理不同飛碟的生產(chǎn)與回收,該工廠必須是場(chǎng)景單實(shí)例的!具體實(shí)現(xiàn)見參考資源 Singleton 模板類

飛碟工廠類的目的是管理飛碟實(shí)例,同時(shí)對(duì)外屏蔽飛碟實(shí)例的的提取和回收細(xì)節(jié)。它可以根據(jù)輪數(shù)不同生產(chǎn)出不同的飛碟,然后對(duì)于被點(diǎn)中或者飛出場(chǎng)景外的飛碟就可以進(jìn)行回收。飛碟工廠從倉(cāng)庫(kù)中獲取這種飛碟,如果倉(cāng)庫(kù)中沒(méi)有,則新的實(shí)例化一個(gè)飛碟,然后添加到正在使用的飛碟列表中。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class DiskFactory : MonoBehaviour {public GameObject disk_prefab = null; private List<DiskData> used = new List<DiskData>(); private List<DiskData> free = new List<DiskData>(); public GameObject GetDisk(int round){ float start_y = -10f; string tag;disk_prefab = null;if (round == 1){tag = "disk1";;}else if(round == 2){tag = "disk2";}else{tag = "disk3";}for(int i=0;i<free.Count;i++){if(free[i].tag == tag){disk_prefab = free[i].gameObject;free.Remove(free[i]);break;}}if(disk_prefab == null){if (tag == "disk1"){disk_prefab = Instantiate(Resources.Load<GameObject>("Prefabs/disk1"), new Vector3(0, start_y, 0), Quaternion.identity);}else if (tag == "disk2"){disk_prefab = Instantiate(Resources.Load<GameObject>("Prefabs/disk2"), new Vector3(0, start_y, 0), Quaternion.identity);disk_prefab.GetComponent<DiskData> ().score = 2;}else{disk_prefab = Instantiate(Resources.Load<GameObject>("Prefabs/disk3"), new Vector3(0, start_y, 0), Quaternion.identity);disk_prefab.GetComponent<DiskData> ().score = 3;}float ran_x = Random.Range(-1f, 1f) < 0 ? -1 : 1;disk_prefab.GetComponent<MeshRenderer> ().material.color = disk_prefab.GetComponent<DiskData>().color;disk_prefab.GetComponent<DiskData>().direction = new Vector3(ran_x, start_y, 0);disk_prefab.GetComponent<DiskData> ().tag = tag;disk_prefab.transform.localScale = disk_prefab.GetComponent<DiskData>().scale;}used.Add(disk_prefab.GetComponent<DiskData>());return disk_prefab;}public void FreeDisk(GameObject disk){for(int i = 0;i < used.Count; i++){if (disk.GetInstanceID() == used[i].gameObject.GetInstanceID()){used[i].gameObject.SetActive(false);free.Add(used[i]);used.Remove(used[i]);break;}}} }

飛碟的參數(shù)類: 包含每個(gè)飛碟的顏色,分?jǐn)?shù),位置,大小,以及是屬于哪個(gè)round的飛碟。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class DiskData : MonoBehaviour {public int score = 1; public Color color = Color.white; public Vector3 direction; public Vector3 scale = new Vector3( 1 ,0.1f, 1); public string tag; }

然后是場(chǎng)景控制器類: 它實(shí)現(xiàn)了接口中的函數(shù)Hit (Vector3 pos);Restart ();GetScore();GameOver ();isCounting()以及getEmitTime ()。游戲開始時(shí)通過(guò)isCounting()以及getEmitTime ()判斷倒計(jì)時(shí)3秒是否完成,若倒計(jì)時(shí)結(jié)束則將counting(是否倒計(jì)時(shí))設(shè)為false并開始發(fā)送飛碟。在每一幀中可以進(jìn)行
InvokeRepeating(“LoadResources”, 1f, speed),即延時(shí)以speed的速度senddisk扔出飛碟,每次得分足夠后就加速speed以更快的方式扔出飛碟,提高游戲難度。Hit函數(shù)實(shí)現(xiàn)了玩家通過(guò)點(diǎn)擊發(fā)出子彈摧毀飛碟。玩家若擊中飛碟則觸發(fā)飛碟的粒子爆炸效果。其他函數(shù)都是與GUI交互的函數(shù)。
在此處滿足了要求:

該工廠必須是場(chǎng)景單實(shí)例的

實(shí)現(xiàn)了singleton類并使用singleton類初始化工廠類,使工廠是場(chǎng)景單實(shí)例的。

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement;public class Controllor : MonoBehaviour,ISceneControllor,IUserAction {public FlyActionManager fam;public DiskFactory df;public UserGUI ug;public ScoreRecorder sr;public RoundControllor rc;private Queue<GameObject> dq = new Queue<GameObject> ();private List<GameObject> dfree = new List<GameObject> ();private GameObject explosion;private float emit_time = 3;private int round = 1;private float t = 1;private float speed = 2;private int score_round = 5;private bool flag = false;private bool game_over = false; private bool counting = true;public bool isCounting(){return counting;}public int getEmitTime(){return (int)emit_time+1;}void Start(){SSDirector director = SSDirector.GetInstance(); director.CurrentSceneControllor = this; df = Singleton<DiskFactory>.Instance;sr = gameObject.AddComponent<ScoreRecorder> () as ScoreRecorder;fam = gameObject.AddComponent<FlyActionManager>() as FlyActionManager;ug = gameObject.AddComponent<UserGUI>() as UserGUI;rc = gameObject.AddComponent<RoundControllor> () as RoundControllor;explosion = Instantiate (Resources.Load<GameObject> ("Prefabs/ParticleSystem1"), new Vector3(0, -100, 0), Quaternion.identity);t = speed;}void Update (){if (emit_time > 0) {counting = true;emit_time -= Time.deltaTime;} else {counting = false;t-=Time.deltaTime;if (t < 0) {LoadResources ();SendDisk ();t = speed;}if ((sr.score >= 10 && round == 1) || (sr.score >= 30 && round == 2)) {round++;rc.loadRoundData (round);}}}public void setting(float speed_,GameObject explosion_){speed = speed_; explosion = explosion_;}public void LoadResources(){dq.Enqueue(df.GetDisk(round)); }private void SendDisk(){float position_x = 16; if (dq.Count != 0){GameObject disk = dq.Dequeue();dfree.Add(disk);disk.SetActive(true);float ran_y = Random.Range(1f, 4f);float ran_x = Random.Range(-1f, 1f) < 0 ? -1 : 1;disk.GetComponent<DiskData>().direction = new Vector3(ran_x, ran_y, 0);Vector3 position = new Vector3(-disk.GetComponent<DiskData>().direction.x * position_x, ran_y, 0);disk.transform.position = position;float power = Random.Range(10f, 15f);float angle = Random.Range(15f, 28f);fam.UFOfly(disk,angle,power);}for (int i = 0; i < dfree.Count; i++){GameObject temp = dfree[i];if (temp.transform.position.y < -10 && temp.gameObject.activeSelf == true){df.FreeDisk(dfree[i]);dfree.Remove(dfree[i]);ug.ReduceBlood();}}}public void Hit (Vector3 pos){Ray ray = Camera.main.ScreenPointToRay(pos);RaycastHit[] hits;hits = Physics.RaycastAll(ray);bool not_hit = false;for (int i = 0; i < hits.Length; i++){RaycastHit hit = hits[i];if (hit.collider.gameObject.GetComponent<DiskData>() != null){for (int j = 0; j < dfree.Count; j++){if (hit.collider.gameObject.GetInstanceID() == dfree[j].gameObject.GetInstanceID()){not_hit = true;}}if(!not_hit){return;}dfree.Remove(hit.collider.gameObject);sr.Record(hit.collider.gameObject);explosion.transform.position = hit.collider.gameObject.transform.position;explosion.GetComponent<ParticleSystem>().Play();hit.collider.gameObject.transform.position = new Vector3(0, -100, 0);df.FreeDisk(hit.collider.gameObject);break;}}}public void Restart (){SceneManager.LoadScene(0);}public int GetScore (){return sr.score;}public void GameOver (){game_over = true;} }

我們還需要一個(gè)記分員類記錄每次的得分:它可以根據(jù)擊中不同加上不同的分?jǐn)?shù)。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class ScoreRecorder : MonoBehaviour {public int score = 0;void Start(){score = 0;}public void Record(GameObject disk){score = score + disk.GetComponent<DiskData> ().score;} }

**接口類:**聲明了需要使用的函數(shù)提供給GUI使用并交給場(chǎng)景控制器實(shí)現(xiàn)。

using System.Collections; using System.Collections.Generic; using UnityEngine;public interface ISceneControllor{void LoadResources (); }public interface IUserAction{void Hit (Vector3 pos);void Restart ();int GetScore();void GameOver ();bool isCounting();int getEmitTime (); }

輪數(shù)控制器類: 實(shí)現(xiàn)了要求

每個(gè) trial 的飛碟的色彩、大小、發(fā)射位置、速度、角度、同時(shí)出現(xiàn)的個(gè)數(shù)都可能不同。它們由該 round 的 ruler 控制;

我可以在類中控制飛碟的發(fā)射間隔以及爆炸效果。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class RoundControllor : MonoBehaviour {private IUserAction action;private float speed;private GameObject explosion;void Start(){action = SSDirector.GetInstance().CurrentSceneControllor as IUserAction;speed = 2;}public void loadRoundData(int round){switch (round){case 1: break;case 2: speed = 1.5f;explosion = Instantiate (Resources.Load<GameObject> ("Prefabs/ParticleSystem2"), new Vector3(0, -100, 0), Quaternion.identity);action.setting (speed,explosion);break;case 3:speed = 1;explosion = Instantiate (Resources.Load<GameObject> ("Prefabs/ParticleSystem3"), new Vector3(0, -100, 0), Quaternion.identity);action.setting (speed,explosion);break;}} }

用戶界面類: GUI中實(shí)現(xiàn)了重新開始功能,顯示生命值,得分以及游戲倒計(jì)時(shí)的功能。游戲倒計(jì)時(shí)即在場(chǎng)景控制器的update記錄消耗的時(shí)間然后取整,若大于0則顯示到屏幕上。通過(guò)接口函數(shù)就可以實(shí)現(xiàn)顯示生命值,得分等功能。然后可以調(diào)用場(chǎng)景控制器中的hit實(shí)現(xiàn)在屏幕上發(fā)射子彈摧毀飛碟。最后直接使用SceneManager.LoadScene(0)即實(shí)現(xiàn)重新開始。

using System.Collections; using System.Collections.Generic; using UnityEngine;public class UserGUI : MonoBehaviour {private IUserAction action;public int life = 6;GUIStyle bold_style = new GUIStyle();GUIStyle text_style = new GUIStyle(); GUIStyle text_style2 = new GUIStyle(); void Start (){action = SSDirector.GetInstance().CurrentSceneControllor as IUserAction;}void OnGUI (){text_style.normal.textColor = new Color(1,1,1, 1);text_style.fontSize = 16;text_style2.normal.textColor = new Color(1,1,1, 1);text_style2.fontSize = 100;if (action.isCounting ()) {GUI.Label(new Rect(Screen.width / 2 - 40, Screen.width / 2 - 300, 50, 50), action.getEmitTime().ToString(), text_style2);} else {if (Input.GetButtonDown("Fire1")){Vector3 pos = Input.mousePosition;action.Hit(pos);}GUI.Label(new Rect(10, 5, 200, 50), "score:", text_style);GUI.Label(new Rect(55, 5, 200, 50), action.GetScore().ToString(), text_style);GUI.Label(new Rect(10, 30, 50, 50), "hp:", text_style);for (int i = 0; i < life; i++){GUI.Label(new Rect(40 + 10 * i, 30, 50, 50), "X", text_style);}if (life == 0){GUI.Label(new Rect(Screen.width / 2 - 50, Screen.width / 2 - 300, 100, 100), "GameOver!", text_style);if (GUI.Button(new Rect(Screen.width / 2 - 60, Screen.width / 2 - 250, 100, 50), "Restart")){action.Restart();return;}action.GameOver();} }}public void ReduceBlood(){if(life > 0)life--;} }

導(dǎo)演類:

using System.Collections; using System.Collections.Generic; using UnityEngine;public class SSDirector : System.Object {private static SSDirector _instance;public ISceneControllor CurrentSceneControllor{ get;set;}public static SSDirector GetInstance(){if (_instance == null) {_instance = new SSDirector ();}return _instance;} }

其他設(shè)定:
預(yù)制設(shè)定如下:

有三種飛碟的預(yù)設(shè)以及每種飛碟對(duì)應(yīng)粒子效果的預(yù)設(shè)。
飛碟的設(shè)置:需要在每個(gè)飛碟上手動(dòng)掛載飛碟的參數(shù)腳本才能使用飛碟的參數(shù)。

粒子效果:持續(xù)實(shí)現(xiàn)1秒且不進(jìn)行循環(huán)即可實(shí)現(xiàn)爆炸效果。

腳本設(shè)置: 常見一個(gè)空游戲?qū)ο?#xff0c;在游戲?qū)ο笊蠏燧d場(chǎng)景控制類以及飛碟工廠類就可以運(yùn)行游戲了。

這樣游戲就完成了!

四.總結(jié)

在這次游戲設(shè)計(jì)中我體會(huì)到了MVC、動(dòng)作管理器的作用,有了這些基本的架構(gòu),我們游戲的實(shí)現(xiàn)更加容易,我們只需實(shí)現(xiàn)場(chǎng)景控制器以及各個(gè)模塊的控制器再通過(guò)MVC架構(gòu)將他們整合就可以得到一個(gè)游戲。
游戲演示:UFO小游戲
github地址:UFO

最后再次感謝師兄的博客供我參考!

總結(jié)

以上是生活随笔為你收集整理的Unity3d--飞碟游戏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。