Unity3d作业||与游戏世界交互
编写一个简单的鼠标打飞碟(Hit UFO)游戏
- 游戏内容要求:
- 游戏有 n 个 round,每个 round 都包括10 次 trial;
- 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
- 每个 trial 的飞碟有随机性,总体难度随 round 上升;
- 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
- 游戏的要求:
- 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
- 近可能使用前面 MVC 结构实现人机交互与游戏模型分离
工厂类模式
- 需要进行频繁的游戏对象的产生和销毁,使用工厂类来减少销毁次数
- 用工厂方法代替new操作的一种模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。**注意事项:**作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
代码实现
-
工厂类
使用工厂类减少游戏的开销,采用工厂模式对飞碟进行管理,进行飞碟的产生和回收
using System.Collections; using System.Collections.Generic; using UnityEngine; using MyGame; public class DiskFactory : MonoBehaviour { private static DiskFactory _instance; public FirstControl sceneControler { get; set; } GameObject diskPrefab; public DiskControl diskData; public List<GameObject> used;//使用队列 public List<GameObject> free;//释放队列 // Use this for initialization //得到实例 public static DiskFactory getInstance() { return _instance; } private void Awake() { if (_instance == null) { _instance = Singleton<DiskFactory>.Instance; _instance.used = new List<GameObject>(); _instance.free = new List<GameObject>(); diskPrefab = Instantiate(Resources.Load<GameObject>("Prefabs/disk"), new Vector3(40, 0, 0), Quaternion.identity); } Debug.Log("instance: " + _instance); } public void Start() { sceneControler = (FirstControl)Director.getInstance().sceneCtrl; Debug.Log(sceneControler); //Debug.Log(this); //Debug.Log(_instance); sceneControler.factory = _instance; Debug.Log("DiskFactory: factory"); //Debug.Log(sceneControler.factory); } //产生新飞碟 public GameObject getDisk(int round) { if (sceneControler.scoreRecorder.Score >= round * 10) { if (sceneControler.user.round < 3) { sceneControler.user.round++; sceneControler.user.num = 0; sceneControler.scoreRecorder.Score = 0; } else { sceneControler.user.game = 2; } } else { if (sceneControler.user.num >= 10) { sceneControler.user.game = 1; } } GameObject newDisk; RoundControl diskOfCurrentRound = new RoundControl(round); if (free.Count == 0) // if no free disk, then create a new disk { newDisk = GameObject.Instantiate(diskPrefab) as GameObject; newDisk.AddComponent<ClickGUI>(); diskData = newDisk.AddComponent<DiskControl>(); } else // else let the first free disk be the newDisk { newDisk = free[0]; free.Remove(free[0]); newDisk.SetActive(true); Debug.Log("get from free"); } diskData = newDisk.GetComponent<DiskControl>(); diskData.color = diskOfCurrentRound.color; //Debug.Log("free: " + free.Count); newDisk.transform.localScale = diskOfCurrentRound.scale * diskPrefab.transform.localScale; newDisk.GetComponent<Renderer>().material.color = diskData.color; used.Add(newDisk); return newDisk; } //释放飞碟 public void freeDisk(GameObject disk1) { used.Remove(disk1); disk1.SetActive(false); free.Add(disk1); Debug.Log("free: " + free.Count); return; } //重新开始 public void Restart() { used.Clear(); free.Clear(); } }
-
场景控制baseCode
-
导演类
public class Director : System.Object { private static Director _instance; public ISceneControl sceneCtrl { get; set; } public bool playing { get; set; } // public static Director getInstance() { if (_instance == null) return _instance = new Director(); else return _instance; } public int getFPS()
-