以前做的项目,复习一下以前写的框架,注: 只针对代码讲解。
数据管理者 因为在游戏中我希望能将游戏的数据储存,或者在外部配置一些数据应用到游戏中,所以用到了json的数据存贮,这里我们直接基于Litjson开源项目来完成这个管理者类。其功能主要便是把数据序列化后储存到本地和将本地数据反序列化应用于游戏中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 using LitJson; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; // 序列化和反序列化Json时 使用的是哪种方案 public enum JsonType { JsonUtlity, LitJson, } // Json数据管理类 主要用于进行Json的序列化存储到硬盘和反序列化从硬盘中读取到内存中 public class JsonMgr { //单例模式,简单说就是将此脚本的代码暴露出去,供其他所有脚本使用,通常用在管理者脚本上 private static JsonMgr instance = new JsonMgr(); public static JsonMgr Instance => instance; private JsonMgr() { } //存储Json数据 序列化 public void SaveData(object data, string fileName, JsonType type = JsonType.LitJson) { //确定存储路径 string path = Application.persistentDataPath + "/" + fileName + ".json"; //序列化 得到Json字符串 string jsonStr = ""; switch (type) { case JsonType.JsonUtlity: jsonStr = JsonUtility.ToJson(data); break; case JsonType.LitJson: jsonStr = JsonMapper.ToJson(data); break; } //把序列化的Json字符串 存储到指定路径的文件中 File.WriteAllText(path, jsonStr); } //读取指定文件中的 Json数据 反序列化 public T LoadData<T>(string fileName, JsonType type = JsonType.LitJson) where T : new() { //确定从哪个路径读取 //首先先判断 默认数据文件夹中是否有我们想要的数据 如果有 就从中获取 string path = Application.streamingAssetsPath + "/" + fileName + ".json"; //先判断 是否存在这个文件 //如果不存在默认文件 就从 读写文件夹中去寻找 if(!File.Exists(path)) path = Application.persistentDataPath + "/" + fileName + ".json"; //如果读写文件夹中都还没有 那就返回一个默认对象 if (!File.Exists(path)) return new T(); //进行反序列化 string jsonStr = File.ReadAllText(path); //数据对象 T data = default(T); switch (type) { case JsonType.JsonUtlity: data = JsonUtility.FromJson<T>(jsonStr); break; case JsonType.LitJson: data = JsonMapper.ToObject<T>(jsonStr); break; } //把对象返回出去 return data; } }
UI管理者类 我们需要一个管理者类来控制和管理我们所有面板的显示以及隐藏,因为我们需要管理不同的面板,所以需要使用模板,此时我们制作面板基类的好处就是,可以通过它来统一管理所有面板,也符合面向对象设计原则。来看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UIManager { //单例模式 private static UIManager instance = new UIManager(); public static UIManager Instance { get => instance; set => instance = value; } //用与显示的面板,每显示一个面板就将其加入字典中,以便于调用 private Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>(); //得到自身的Transform, private Transform canvasTrans; //初始化 private UIManager() { //创建canvas空白画布 GameObject canvas = GameObject.Instantiate(Resources.Load<GameObject>("UI/Canvas")); //把画布位置保存下来 canvasTrans = canvas.transform; //防止场景加载的时候被销毁 GameObject.DontDestroyOnLoad(canvas); } //传入想调用的面板,来将它显示 public T showPanel<T>(bool isFade = true) where T:BasePanel { //type(T)获取该对象,并取得其名字 string panelName = typeof(T).Name; //查看字典中有无该面板,如果有表明已经显示,直接return该面板,注意此处要将BasePanel重新转换为子类类型 if (panelDic.ContainsKey(panelName)) { return panelDic[panelName] as T; } //显示面板 根据面板名字 动态创建预制体 设置父对象 GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>("UI/" + panelName)); panelObj.transform.SetParent(canvasTrans, false); //指向面板上 显示逻辑 并且把它保存起来 T panel = panelObj.GetComponent<T>(); //把这个面板脚本 存储在字典中方便之后的获取和隐藏; panelDic.Add(panelName, panel); panel.ShowMe(isFade); return panel; } //隐藏面板 public void HidePanel<T>(bool isFade = true) where T:BasePanel { //根据泛型取得名字 string panelName = typeof(T).Name; //如果存在,调用其基类的HideMe函数,并传入lambda让其释放内存并在字典中删除 if (panelDic.ContainsKey(panelName)) { if (isFade) { panelDic[panelName].HideMe(() => { //删除对象 GameObject.Destroy(panelDic[panelName].gameObject); //删除字典里面储存 面板脚本 panelDic.Remove(panelName); }); } else { //删除对象 GameObject.Destroy(panelDic[panelName].gameObject); //删除字典里面储存 面板脚本 panelDic.Remove(panelName); } } } //得到面板 public T GetPanel<T>() where T:BasePanel { string panelName = typeof(T).Name; if (panelDic.ContainsKey(panelName)) { return panelDic[panelName] as T; } else { return null; } } }
有了这个脚本,我们就可以非常方便的调出和删除面板,所有的UI控制我们都可以使用此脚本来实现。