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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

unity 实现简易打飞碟游戏

發(fā)布時間:2023/12/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity 实现简易打飞碟游戏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

unity 實(shí)現(xiàn)簡易打飛碟游戲

一、簡介

游戲共有5個回合,每個回合中會有隨機(jī)產(chǎn)生的飛碟飛過屏幕,玩家需要做的事情就是用鼠標(biāo)盡量快和多地點(diǎn)擊飛碟。
每個飛碟對應(yīng)一定的分?jǐn)?shù),目前的設(shè)置是:
【紅色飛碟 3分】、【綠色飛碟 2分】、【藍(lán)色飛碟 1分】
游戲的目的是在規(guī)定回合內(nèi)得到盡可能高的分?jǐn)?shù)。

二、實(shí)現(xiàn)效果

三、代碼框架

基本延用了上一個游戲中的框架,包括動作與動作管理器、場景控制器和用戶GUI,更新的部分包括:

  • 動作由移動船只、移動角色變成了移動飛碟
  • 將主控制器的功能分散到幾個控制器上,包括分?jǐn)?shù)控制器、飛碟產(chǎn)生器
  • 增加了場景單實(shí)例的代碼

四、具體實(shí)現(xiàn)

(一)Actions動作與動作管理器
1. SSAction 動作基類
public class SSAction : ScriptableObject {public bool enable = true;public bool destroy = false;public GameObject gameObject { get; set;}public Transform transform {get; set;}public IActionCallback callback {get; set;}protected SSAction() {}// Start is called before the first frame updatepublic virtual void Start(){throw new System.NotImplementedException();}// Update is called once per framepublic virtual void Update(){throw new System.NotImplementedException();} }
2. CCFlyAction 飛碟動作類

飛碟的運(yùn)動有簡單的兩個屬性:水平方向速度和垂直方向速度。
飛碟從飛碟工廠出來的時候被定位在相機(jī)視角邊緣,隨著運(yùn)動進(jìn)入相機(jī)視角,在被玩家點(diǎn)擊或者飛出相機(jī)視角(即玩家不能再看到它時)時,飛碟和動作一起被銷毀。

//飛碟從界面左右兩側(cè)飛入,離開界面時運(yùn)動結(jié)束 public class CCFlyAction : SSAction {public float speedX;public float speedY;public static CCFlyAction GetSSAction(float x, float y) {CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();action.speedX = x;action.speedY = y;return action;}// Start is called before the first frame updatepublic override void Start(){}// Update is called once per framepublic override void Update(){//Debug.Log("flyaction update");if (this.transform.gameObject.activeSelf == false) {//飛碟已經(jīng)被"銷毀"this.destroy = true;this.callback.SSActionEvent(this);return;}Vector3 vec3 = Camera.main.WorldToScreenPoint (this.transform.position);if (vec3.x < -100 || vec3.x > Camera.main.pixelWidth + 100 || vec3.y < -100 || vec3.y > Camera.main.pixelHeight + 100) {this.destroy = true;this.callback.SSActionEvent(this);return;}transform.position += new Vector3(speedX, speedY, 0) * Time.deltaTime * 2;} }
3. IActionCallback 事件回調(diào)接口
public enum SSActionEventType:int {Started, Completed} public interface IActionCallback {//回調(diào)函數(shù)void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,int intParam = 0,string strParam = null,Object objectParam = null); }
4. SSActionManager 動作管理類基類

新增了一個函數(shù)RemainActionCount(),用于判斷每回合中剩余的動作數(shù)量(即飛碟數(shù)量),只有這個值為0才進(jìn)入下一回合。

public class SSActionManager : MonoBehaviour {private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();private List<SSAction> waitingAdd = new List<SSAction>();private List<int> waitingDelete = new List<int>(); // Start is called before the first frame updateprotected void Start(){}// Update is called once per frameprotected void Update(){//Debug.Log("ssactionmanager update");foreach (SSAction ac in waitingAdd) {actions[ac.GetInstanceID()] = ac;}waitingAdd.Clear();//Debug.Log(actions.Count);foreach(KeyValuePair<int, SSAction> kv in actions) {SSAction ac = kv.Value;if (ac.destroy) {waitingDelete.Add(ac.GetInstanceID());} else if (ac.enable) {//Debug.Log("ssactionmanager update");ac.Update();}}foreach(int key in waitingDelete) {SSAction ac = actions[key];actions.Remove(key);Destroy(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameObject, SSAction action, IActionCallback manager) {//Debug.Log("run action");action.gameObject = gameObject;action.transform = gameObject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}public int RemainActionCount() {return actions.Count;} }
5. CCActionManager 動作管理類

動作結(jié)束時會調(diào)用動作管理者實(shí)現(xiàn)的回調(diào)函數(shù),即IActionCallback接口中的SSActionEventType,動作管理者將動作綁定的游戲?qū)ο?#xff08;飛碟)銷毀。

public class CCActionManager : SSActionManager, IActionCallback {public RoundController sceneController;public CCFlyAction action;// Start is called before the first frame updateprotected new void Start(){sceneController = (RoundController)SSDirector.getInstance().currentSceneController;sceneController.actionManager = this;}// Update is called once per frame// protected new void Update()// {// }public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,int intParam = 0,string strParam = null,Object objectParam = null) {factory.FreeDisk(source.transform.gameObject);}public void MoveDisk(GameObject disk) {action = CCFlyAction.GetSSAction(disk.GetComponent<DiskAttributes>().speedX, disk.GetComponent<DiskAttributes>().speedY);RunAction(disk, action, this);} }
(二)Controllers 控制器
1. DiskFactory 飛碟生成器

用于生產(chǎn)飛碟。

GetDisk(int round)被主控制器調(diào)用,round(回合數(shù))會影響所生產(chǎn)的飛碟的速度、大小等屬性。
有兩個列表used和free,存放的是飛碟屬性(包括分?jǐn)?shù)、速度),可以循環(huán)使用,提高飛碟的產(chǎn)生效率。

飛碟初始位置隨機(jī),可能為屏幕的四個角落之一。
根據(jù)飛碟的分?jǐn)?shù)和回合數(shù)設(shè)置飛碟的大小和速度。

public class MyException : System.Exception {public MyException() { }public MyException(string message) : base(message) { } } public class DiskAttributes : MonoBehaviour {//public GameObject gameobj;public int score;public float speedX;public float speedY; } public class DiskFactory : MonoBehaviour {List<GameObject> used;List<GameObject> free;System.Random rand;// Start is called before the first frame updatevoid Start(){used = new List<GameObject>();free = new List<GameObject>();rand = new System.Random();//Disk disk = GetDisk(1); }public GameObject GetDisk(int round) {GameObject disk;if (free.Count != 0) {disk = free[0];free.Remove(disk);}else {disk = GameObject.Instantiate(Resources.Load("Prefabs/disk", typeof(GameObject))) as GameObject;disk.AddComponent<DiskAttributes>();}//根據(jù)不同round設(shè)置diskAttributes的值//隨意的旋轉(zhuǎn)角度disk.transform.localEulerAngles = new Vector3(-rand.Next(20,40),0,0);DiskAttributes attri = disk.GetComponent<DiskAttributes>();attri.score = rand.Next(1,4);//由分?jǐn)?shù)來決定速度、顏色、大小attri.speedX = (rand.Next(1,5) + attri.score + round) * 0.2f;attri.speedY = (rand.Next(1,5) + attri.score + round) * 0.2f;if (attri.score == 3) {disk.GetComponent<Renderer>().material.color = Color.red;disk.transform.localScale += new Vector3(-0.5f,0,-0.5f);}else if (attri.score == 2) {disk.GetComponent<Renderer>().material.color = Color.green;disk.transform.localScale += new Vector3(-0.2f,0,-0.2f);}else if (attri.score == 1) {disk.GetComponent<Renderer>().material.color = Color.blue;}//飛碟可從四個方向飛入(左上、左下、右上、右下)int direction = rand.Next(1,5);if (direction == 1) {disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(0, Camera.main.pixelHeight * 1.5f, 8)));attri.speedY *= -1;}else if (direction == 2) {disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(0, Camera.main.pixelHeight * 0f, 8)));}else if (direction == 3) {disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(Camera.main.pixelWidth, Camera.main.pixelHeight * 1.5f, 8)));attri.speedX *= -1;attri.speedY *= -1;}else if (direction == 4) {disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(Camera.main.pixelWidth, Camera.main.pixelHeight * 0f, 8)));attri.speedX *= -1;}used.Add(disk);disk.SetActive(true);Debug.Log("generate disk");return disk;}public void FreeDisk(GameObject disk) {disk.SetActive(false);//將位置和大小恢復(fù)到預(yù)制,這點(diǎn)很重要!disk.transform.position = new Vector3(0, 0,0);disk.transform.localScale = new Vector3(2f,0.1f,2f);if (!used.Contains(disk)) {throw new MyException("Try to remove a item from a list which doesn't contain it.");}Debug.Log("free disk");used.Remove(disk);free.Add(disk);} }
2. Singleton 單實(shí)例代碼

用于單實(shí)例化飛碟工廠

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour {protected static T instance;public static T Instance { get { if (instance == null) { instance = (T)FindObjectOfType (typeof(T)); if (instance == null) { Debug.LogError ("An instance of " + typeof(T) +" is needed in the scene, but there is none."); } } return instance; } } }

可以這樣使用:

DiskFactory factory = Singleton<DiskFactory>.Instance;
3. ISceneController 場景控制器接口

其中包含的方法必須被主控制器實(shí)現(xiàn)。

public interface ISceneController {void LoadSource(); }
4. SSDirector 導(dǎo)演類
public class SSDirector : System.Object {private static SSDirector _instance;public ISceneController currentSceneController {get; set;}public static SSDirector getInstance() {if (_instance == null) {_instance = new SSDirector();}return _instance;} }
5. ScoreController 計分器

初始化時將自身設(shè)置為主控制器的分?jǐn)?shù)控制器。

public class ScoreController : MonoBehaviour {int score;public RoundController roundController;public UserGUI userGUI;// Start is called before the first frame updatevoid Start(){roundController = (RoundController)SSDirector.getInstance().currentSceneController;roundController.scoreController = this;userGUI = this.gameObject.GetComponent<UserGUI>();}public void Record(GameObject disk) {score += disk.GetComponent<DiskAttributes>().score;userGUI.score = score;}}
6. RoundController 主控制器

連接用戶與游戲,分別需要實(shí)現(xiàn)場景控制器的接口和用戶操作的接口。
Update的主要工作:在每個回合中從工廠獲取飛碟,為飛碟綁定動作,令其開始運(yùn)動。

public class RoundController : MonoBehaviour, ISceneController, IUserAction {int round = 0;int max_round = 5;float timer = 0.5f;GameObject disk;DiskFactory factory ;public CCActionManager actionManager;public ScoreController scoreController;public UserGUI userGUI;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){if (userGUI.mode == 0) return;GetHit();gameOver();if (round > max_round) {return;}timer -= Time.deltaTime;if (timer <= 0 && actionManager.RemainActionCount() == 0) {//從工廠中得到10個飛碟,為其加上動作for (int i = 0; i < 10; ++i) {disk = factory.GetDisk(round);actionManager.MoveDisk(disk);//Thread.Sleep(100);}round += 1;if (round <= max_round) {userGUI.round = round;}timer = 4.0f;}}void Awake() {SSDirector director = SSDirector.getInstance();director.currentSceneController = this;director.currentSceneController.LoadSource();gameObject.AddComponent<UserGUI>();gameObject.AddComponent<CCActionManager>();gameObject.AddComponent<ScoreController>();gameObject.AddComponent<DiskFactory>();factory = Singleton<DiskFactory>.Instance;userGUI = gameObject.GetComponent<UserGUI>();}public void LoadSource() {}public void gameOver() {if (round > max_round && actionManager.RemainActionCount() == 0)userGUI.gameMessage = "Game Over!";}public void GetHit() {if (Input.GetButtonDown("Fire1")) {Camera ca = Camera.main;Ray ray = ca.ScreenPointToRay(Input.mousePosition);//Return the ray's hitRaycastHit hit;if (Physics.Raycast(ray, out hit)) {scoreController.Record(hit.transform.gameObject);hit.transform.gameObject.SetActive(false);}}} }
(三)Viewers 用戶接口與用戶GUI
1. IUserAction 用戶接口
public interface IUserAction {void gameOver();void GetHit(); }
2. UserGUI 用戶界面
public class UserGUI : MonoBehaviour {public int mode;public int score;public int round;public string gameMessage;private IUserAction action;public GUIStyle bigStyle, blackStyle, smallStyle;//自定義字體格式public Font pixelFont;private int menu_width = Screen.width / 5, menu_height = Screen.width / 10;//主菜單每一個按鍵的寬度和高度// Start is called before the first frame updatevoid Start(){mode = 0;gameMessage = "";action = SSDirector.getInstance().currentSceneController as IUserAction;//pixelStyle//pixelFont = Font.Instantiate(Resources.Load("Fonts/ThaleahFat", typeof(Font))) as Font;//if (pixelFont == null) Debug.Log("null");//pixelFont.fontSize = 50;//pixelFont = Arial;//大字體初始化bigStyle = new GUIStyle();bigStyle.normal.textColor = Color.white;bigStyle.normal.background = null;bigStyle.fontSize = 50;bigStyle.alignment=TextAnchor.MiddleCenter;//blackblackStyle = new GUIStyle();blackStyle.normal.textColor = Color.black;blackStyle.normal.background = null;blackStyle.fontSize = 50;blackStyle.alignment=TextAnchor.MiddleCenter;//小字體初始化smallStyle = new GUIStyle();smallStyle.normal.textColor = Color.white;smallStyle.normal.background = null;smallStyle.fontSize = 20;smallStyle.alignment=TextAnchor.MiddleCenter;}// Update is called once per framevoid Update(){}void OnGUI() {//GUI.skin.button.font = pixelFont;GUI.skin.button.fontSize = 35;switch(mode) {case 0:mainMenu();break;case 1:GameStart();break;} }void mainMenu() {GUI.Label(new Rect(Screen.width / 2 - menu_width * 0.5f, Screen.height * 0.1f, menu_width, menu_height), "Hit UFO", bigStyle);bool button = GUI.Button(new Rect(Screen.width / 2 - menu_width * 0.5f, Screen.height * 3 / 7, menu_width, menu_height), "Start");if (button) {mode = 1;}}void GameStart() {GUI.Label(new Rect(300, 60, 50, 200), gameMessage, bigStyle);GUI.Label(new Rect(0,0,100,50), "Score: " + score, smallStyle);GUI.Label(new Rect(560,0,100,50), "Round: " + round, smallStyle);} }

五、項目地址

github地址

六、可改進(jìn)的地方

  • 尋找合適的飛碟或飛盤貼圖,增加自旋效果
  • 給飛碟加上更復(fù)雜的軌跡,比如上下左右起伏
  • 增加擊中飛碟時的畫面效果,比如飛碟破碎或爆炸

總結(jié)

以上是生活随笔為你收集整理的unity 实现简易打飞碟游戏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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