如果你的使用工厂有疑问,参考:弹药和敌人:减少,重用和再利用;参考:Unity对象池(Object Pooling)理解与简单应用 代码质量较低,比较凌乱
Controller 负责统筹各个组件之间的关系,所以在其中我们需要设置一下几个成员变量:_UFOfactory、_director、my_diskfactory ,并对其进行初始化、实例化。需要注意的是, _UFOfactory 采用的是单例模式。
public class Controller : MonoBehaviour { public UFOFactory _UFOfactory; public Director _director; private GameObject my_diskfactory; void Awake() { Random.InitState((int)System.DateTime.Now.Ticks); my_diskfactory = new GameObject("Disk_Factory"); my_diskfactory.AddComponent<UFOFactory>(); _director = Director.getInstance(); _UFOfactory = Singleton<UFOFactory>.Instance; _director.currentController = this; } } UFOaction UFOaction 定义了UFO的飞行动作,其中: (1)成员变量: public Director _director; public GameObject player; //记录该动作所归属的对象 Vector3 start; //记录UFO飞行的初始位置 Vector3 end; //记录UFO飞行的结束位置 public int speed=3; //记录UFO飞行的速度 public bool running = true;//运行态标志位(2)成员函数 a. Start() 设置UFO 开始位置 以及 结束位置 ,并调用 setColor函数 调整其颜色。
public void Start() { _director = Director.getInstance(); start = new Vector3(Random.Range(-20f,20f), Random.Range(-20f, 20f), 0); if (start.x < 10 && start.x > -10) start.x *= 4; if (start.y < 10 && start.y > -10) start.y *= 4; end = new Vector3(-start.x, -start.y, 0); player.transform.position = start; setColor(); }b. Update() 使用 MoveTowards函数 移动UFO。并且判定UFO是否移动到其结束位置,若是移动到其结束位置,证明其未被集中,则调用 not_hit 函数,回收UFO。
public void Update() { if (running) { player.transform.position = Vector3.MoveTowards(player.transform.position, end, speed * Time.deltaTime); if (player.transform.position == end) { this._director.currentController._UFOfactory.not_hit(this.player); } } }c. setColor() 使用 Random 随机一个数,并根据这个数设置UFO的颜色。
public void setColor() { int color = Random.Range(1, 4); switch (color) { case 1: player.GetComponent<MeshRenderer>().material.color = Color.red; foreach (Transform child in player.transform) { child.gameObject.GetComponent<MeshRenderer>().material.color = Color.red; } break; case 2: player.GetComponent<MeshRenderer>().material.color = Color.yellow; foreach (Transform child in player.transform) { child.gameObject.GetComponent<MeshRenderer>().material.color = Color.yellow; } break; case 3: player.GetComponent<MeshRenderer>().material.color = Color.blue; foreach (Transform child in player.transform) { child.gameObject.GetComponent<MeshRenderer>().material.color = Color.blue; } break; default: break; } } UFOfactory UFOfactory整合了UFO的动作管理员。 (1)成员变量 public List<GameObject> used; //存储已经放飞的UFO public List<GameObject> not_used; //存储飞回来了的UFO public List<UFO_action> actions; //存储UFO动作,小型动作管理器 public int round = 0; //阶段 public int score = 0; //得分(2)成员函数 a. Start() 为各个List指针创建List对象,并为各个List添加其对应成员。并为各个 UfO_action 绑定对应的 Player 。
private void Start() { used = new List<GameObject>(); not_used = new List<GameObject>(); actions = new List<UFO_action>(); for(int i = 0; i < 10; i++) { not_used.Add(Object.Instantiate(Resources.Load("Prefabs/UFO", typeof(GameObject)), new Vector3(0, -20, 0), Quaternion.identity, null) as GameObject); actions.Add(ScriptableObject.CreateInstance<UFO_action>()); } for(int i = 0; i < 10; i++) { actions[i].player = not_used[i]; } }b. Update() 调用各个 处于工作状态的UFO_action 的 Update函数 ,在 round < 10 的时候调用 get_ready函数 来更新轮次。并在 round == 11 的时候停止对 UFO_action 的操作。
private void Update() { if (round <= 10) { for (int i = 0; i < 10; i++) { actions[i].Update(); } if (not_used.Count == 10) { round += 1; if (round <= 10) get_ready(round); } } }c. hitted(GameObject g) 判别被击中的UFO是什么色的,并对应给分。将击中的UFO从 used列表 移动到 not_used列表 ,并调整其为初始位置,再将其对应的 UFO_action 调为非running。
public void hitted(GameObject g) { if (g.gameObject.GetComponent<MeshRenderer>().material.color == Color.red) score += 3; else if (g.gameObject.GetComponent<MeshRenderer>().material.color == Color.yellow) score += 2; else if (g.gameObject.GetComponent<MeshRenderer>().material.color == Color.blue) score += 1; this.used.Remove(g); g.transform.position = new Vector3(0, -20, 0); for(int i = 0; i < 10; i++) { if (actions[i].player == g) actions[i].running = false; } this.not_used.Add(g); }d. not_hit(GameObject g) not_hit函数 与 hitted函数相似,但减去了加分的环节。
public void not_hit(GameObject g) { this.used.Remove(g); g.transform.position = new Vector3(0, -20, 0); for (int i = 0; i < 10; i++) { if (actions[i].player == g) actions[i].running = false; } this.not_used.Add(g); }e. get_ready(int round) 用于做UFO起飞之前的准备工作,它将 not_used列表中所有的UFO移入 used列表 并按轮次调整其飞行速度,并调用 UFO_action 的 Start函数 做初始化,并将其设为 running态 。
public void get_ready(int round) { for(int i = 0; i < 10; i++) { used.Add(not_used[0]); not_used.Remove(not_used[0]); actions[i].speed = round + 3; actions[i].Start(); actions[i].running = true; } } Hit_UFO 使用 Ray 来定位鼠标的位置以及鼠标点击到的游戏物体,当点击到物体的时候调用 UFOfactory 的 hitted函数。 public class Hit_UFO : MonoBehaviour { public GameObject cam; public Director director; private void Start() { director = Director.getInstance(); } // Update is called once per frame void Update() { if (Input.GetButtonDown("Fire1")) { Vector3 mp = Input.mousePosition; //get Screen Position //create ray, origin is camera, and direction to mousepoint Camera ca; if (cam != null) ca = cam.GetComponent<Camera>(); else ca = Camera.main; Ray ray = ca.ScreenPointToRay(Input.mousePosition); //Return the ray's hit RaycastHit hit; if (Physics.Raycast(ray, out hit)) { director.currentController._UFOfactory.hitted(hit.transform.gameObject); } } } } My_GUI 创建 Score 和 Round 的label。并在轮次到达11的时候,停止显示 Score 和 Round ,而在屏幕中间显示 Final Score 。 private void OnGUI() { int my_round = _director.currentController._UFOfactory.round; if (my_round == 11) { GUIStyle ending = new GUIStyle(); ending.normal.background = null; ending.normal.background = null; ending.normal.textColor = new Color(0, 0, 0); ending.fontSize = 80; string ending_score = "Final Score: " + _director.currentController._UFOfactory.score.ToString(); GUI.Label(new Rect(0.13f * Screen.width, 0.4f * Screen.height, 300, 300), ending_score, ending); } else { string round = my_round.ToString(); round = "Round: " + round; GUIStyle bb = new GUIStyle(); //创建GUI的格式 bb.normal.background = null; bb.normal.textColor = new Color(0, 0, 0); bb.fontSize = 25; GUI.Label(new Rect(0.8f * Screen.width, 240, 150, 35), round, bb); string score = _director.currentController._UFOfactory.score.ToString(); score = "Score:" + score; GUI.Label(new Rect(0.8f * Screen.width, 270, 150, 35), score, bb); } } Singleton使用 FindObjectOfType 来寻找一个类型的单例,并返回这个单例。
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("No instance of " + typeof(T)); } } return instance; } } } 游戏截图用自定义组件定义几种飞碟,做成预制 参考官方脚本手册 https://docs.unity3d.com/ScriptReference/Editor.html 实现自定义组件,编辑并赋予飞碟一些属性
例如编写旋转脚本组件,让UFO使用不同的转动轴进行转动。通过,使用不同的速度与轴方向,就可以让我们的UFO按照不同的旋转轴旋转。将设计好的不同的组件挂载到不同的UFO上,就做好了几种飞碟的预制。
public class around : MonoBehaviour { public float speed; public float yangle, zangle; void Update() { Vector3 axis = new Vector3(0, yangle, zangle); this.transform.RotateAround(new Vector3(0, 0, 0), axis, speed * Time.deltaTime); this.transform.Rotate(Vector3.up * 100 * Time.deltaTime); } }我的github
