Unity学习记录——与游戏世界交互 前言
? 本文是中山大学软件工程学院2020级3d游戏编程与设计的作业5
编程题:简单打飞碟 1. 题目要求2. 基本介绍
? 本次简单打飞碟小游戏使用了工厂模式管理不同飞碟的生产与回收 。
? **工厂模式( )**是 游戏开发中最常用的设计模式之一 。该模式将实例化对象的代码提取出来,放到一个类中统一管理和维护 , 达到和主项目的依赖关系的解耦 。从而提高项目的扩展和维护性 。也因此 , 在工厂模式中,我们在创建对象时不会对用户暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象 。
3.代码解读
? 本次代码仍旧使用了MVC模式,同时进行了动作分离 。
? 由于动作分离中动作基类等代码基本一致,本次编程题中,一部分代码使用了上次作业(牧师与魔鬼动作分离版本)中的代码,复用的代码分别为:(),(),()三个类 。
? 同时 , ()与()两个类的设计在这三次游戏编程中也是基本一致 , 此处不进行介绍 。
? 以下为代码解读:
? 飞碟的动作类 。控制飞碟的飞行 。实现的逻辑为根据飞碟的位置决定飞碟的运动,当飞碟位置在一定范围内时进行我们所设计的模拟位移,超出一定范围之后就停止位移,等待工厂的回收 。
public class FlyAction : SSAction{public float gravity = -1;//向下的加速度private Vector3 start_vector;//初速度向量private Vector3 gravity_vector = Vector3.zero;//加速度的向量,初始时为0private Vector3 current_angle = Vector3.zero;//当前时间的欧拉角private float time;//已经过去的时间private FlyAction() { }public static FlyAction GetSSAction(int lor, float angle, float power){//初始化物体将要运动的初速度向量FlyAction action = CreateInstance
? 飞碟的动作管理类 。通过调用控制飞碟的运动 。
public class FlyActionManager : SSActionManager{public FlyAction fly;public FirstController scene_controller;protected void Start(){scene_controller = (FirstController)SSDirector.GetInstance().CurrentSceneController;scene_controller.action_manager = this;}public void DiskFly(GameObject disk, float angle, float power){int loc = disk.transform.position.x < 0 ? 1 : -1;fly = FlyAction.GetSSAction(loc, angle, power);this.RunAction(disk, fly, this);}}
Judge
? 裁判类 。由于游戏到达第三回合之后就直接停止,裁判类无需再判断游戏的终止条件,只是进行游戏分数的记录 。
public class Judge : MonoBehaviour{private float score;void Start(){score = 0;}public void Record(GameObject disk){score += disk.GetComponent
? 场景单实例类 。当所需的实例第一次被需要时,在场景内搜索该实例,下一次使用时不需要搜索直接返回 。
public class Singleton : 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;}}}
? 负责游戏第一个场景的搭载 。
? 在之中还编写了获取相应数值的(),重新开始游戏的实现游戏的(),游戏结束的()等小部件函数 。
? 而更为重要的函数为()、Hit()、()三个函数 。
? ()检测每一帧的鼠标点击是否命中目标,同时根据此时的回合数设置不同的游戏难度 。此处变量count用来控制飞碟的发射速度以及游戏回合切换的暂停时间:每经过一帧count加1,当count到达相应数值就发射飞碟,当回合结束时 , 使count在一定数值的帧内不再增加(此处引入变量hold来进行此操作),即可暂停发射飞碟并在此时插入切换回合的UI 。
? Hit()检测射线与飞碟是否碰撞,如碰撞则计分并回收飞碟 。
? ()从工厂中拿飞碟并根据种类设置一定范围内的随机发射参数,然后调用动作管理器执行发射飞碟的动作 。
public class FirstController : MonoBehaviour, ISceneController, IUserAction{public FlyActionManager action_manager;public DiskFactory disk_factory;public UserGUI user_gui;public Judge judge;private int round = 1;private int trial = 0;private bool running = false;private int count = 0;public bool stop = false;public int hold = 0;void Start(){SSDirector director = SSDirector.GetInstance();director.CurrentSceneController = this;disk_factory = Singleton
Disk
? 包括了飞碟类型type,分数score,颜色color三个属性 , 可以通过这些属性设置飞碟预制件的属性
![Unity学习记录——与游戏世界交互](http://img.gansulong.com/240106/1252414960-0.gif)
文章插图
public class Disk : MonoBehaviour{public int type = 1;public int score = 1;public Color color = Color.white;}
? Disk的工厂 。主要进行飞碟的生产与回收 。
? 在本函数之中,维护两个列表,一个是使用中的飞碟,一个是空闲飞碟 。当场景控制器需要获取一个飞碟时,先在空闲列表中寻找可用的空闲飞碟,如果找不到就根据预制重新实例化一个飞碟 。回收飞碟的逻辑为遍历使用列表,当有飞碟已经完成了所有动作,即位置在摄像机之下 , 则回收 。
public class DiskFactory : MonoBehaviour{private List used = new List();private List free = new List();public GameObject GetDisk(int type){GameObject disk_prefab = null;//寻找空闲飞碟,如果无空闲飞碟则重新实例化飞碟if (free.Count > 0){for (int i = 0; i < free.Count; i++){if (free[i].type == type){disk_prefab = free[i].gameObject;free.Remove(free[i]);break;}}}if (disk_prefab == null){if (type == 1){disk_prefab = Instantiate(Resources.Load("Prefabs/disk1"),new Vector3(0, -10f, 0), Quaternion.identity);}else if (type == 2){disk_prefab = Instantiate(Resources.Load("Prefabs/disk2"),new Vector3(0, -10f, 0), Quaternion.identity);}else{disk_prefab = Instantiate(Resources.Load("Prefabs/disk3"),new Vector3(0, -10f, 0), Quaternion.identity);}disk_prefab.GetComponent().material.color = disk_prefab.GetComponent().color;}used.Add(disk_prefab.GetComponent());disk_prefab.SetActive(true);return disk_prefab;}public void FreeDisk(){for (int i = 0; i < used.Count; i++){if (used[i].gameObject.transform.position.y <= -10f){free.Add(used[i]);used.Remove(used[i]);}}}public void Reset(){FreeDisk();}}
? UI代码 , 显示回合切换以及游戏开始结束、游戏进行时的UI 。
public class UserGUI : MonoBehaviour{private IUserAction action;//每个GUI的styleGUIStyle bold_style = new GUIStyle();GUIStyle text_style = new GUIStyle();GUIStyle over_style = new GUIStyle();GUIStyle round_style = new GUIStyle();private bool game_start = false;private int wid = Screen.width;private int heig = Screen.height;void Start(){action = SSDirector.GetInstance().CurrentSceneController as IUserAction;}void OnGUI(){bold_style.normal.textColor = new Color(1, 0, 0);bold_style.fontSize = 16;text_style.normal.textColor = new Color(0, 0, 0, 1);text_style.fontSize = 16;over_style.normal.textColor = new Color(1, 0, 0);over_style.fontSize = 25;round_style.normal.textColor = new Color(1, 0, 0);round_style.fontSize = 70;if (game_start && !action.GetStop()){GUI.Label(new Rect(wid - 150, 5, 200, 50), "分数:" + action.GetScore().ToString(), text_style);GUI.Label(new Rect(100, 5, 50, 50), "Round:" + action.GetRound().ToString(), text_style);GUI.Label(new Rect(180, 5, 50, 50), "Trial:" + action.GetTrial().ToString(), text_style);if (action.GetRound() == 3 && action.GetTrial() == 10){GUI.Label(new Rect(wid / 2 - 20, heig / 2 - 100, 100, 100), "游戏结束", over_style);GUI.Label(new Rect(wid / 2 - 10, heig / 2 - 50, 50, 50), "你的分数:" + action.GetScore().ToString(), text_style);if (GUI.Button(new Rect(wid / 2 - 20, heig / 2, 100, 50), "重新开始")){action.ReStart();return;}action.GameOver();}}else if (game_start && action.GetStop()){if (action.GetHold() > 300 && action.GetRound() <= 3 && action.GetTrial() == 0){GUI.Label(new Rect(wid / 2 - 110, heig / 2 - 60, 100, 100), "Round" + (action.GetRound()).ToString(), round_style);}if (action.GetRound() == 1){GUI.Label(new Rect(wid / 2 - 110, heig / 2 - 60, 100, 100), "Round" + (action.GetRound()).ToString(), round_style);}}else{GUI.Label(new Rect(wid / 2 - 60, heig / 2 - 100, 100, 100), "简单打飞碟", over_style);GUI.Label(new Rect(wid / 2 - 50, heig / 2 - 50, 100, 100), "鼠标点击飞碟", text_style);if (GUI.Button(new Rect(wid / 2 - 50, heig / 2, 100, 50), "游戏开始")){game_start = true;action.ReStart();}}}}
4.演示
? 演示gif图入下:
? 提醒:本次游戏项目在运行时是默认打开垂直同步的 , 开关在如下图所示位置:
? 如果关闭了垂直同步,游戏帧率会变高,但是也会体验到地狱绘卷难度的打飞碟,如下所示:
代码位置
【Unity学习记录——与游戏世界交互】? 代码以及文档均已经上传至hw5 · / - gitee
- 如何学习学习强国
- 学习强国怎么邀请好友对战
- 【火炉炼AI】机器学习011-分类模型的评估:准确率,精确率,召回率,F1值
- 怎么查看情侣空间历史记录 怎么查看情侣空间历史
- 微信怎么查找以前的聊天记录? 微信怎么查找以前的聊天记录
- 微信恢复聊天记录方法 微信恢复聊天记录
- 以前手机的微信聊天记录怎么恢复 换手机微信聊天记录怎么恢复
- oppo手机qq聊天记录在哪个文件夹 手机qq聊天记录在哪个文件夹
- 短信和通话记录怎么转移到新手机 通话记录怎么转移到新手机
- Mysql-存储过程 学习整理