2.准备工作
2.1 知识点
创建Unity和FGUI工程
FGUI导入美术资源 项目设置中设计分辨率
导入Unity商店中FGUI的SDK
导入UIManager 删除之前Teach和注册组件相关
导入二进制相关的包
2.2 知识点代码
UIManager
using FairyGUI;
using Login;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
private static UIManager instance = new UIManager();
public static UIManager Instance => instance;
//用于存储已经显示的 UI面板
private Dictionary<string, GComponent> panelDic = new Dictionary<string, GComponent>();
//用于存储已经显示的 窗口
private Dictionary<string, Window> windowDic = new Dictionary<string, Window>();
private UIManager()
{
//默认字体
UIConfig.defaultFont = "UI/STHUPO";
//默认音效
UIPackage.AddPackage("UI/Public");
UIConfig.buttonSound = (NAudioClip)UIPackage.GetItemAssetByURL("ui://Public/btnMusic");
//适配相关的设置
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
//设置模态半透明程度
UIConfig.modalLayerColor = new Color(0, 0, 0, 0.5f);
//注册相关的代码
LoginBinder.BindAll();
}
//组件名和面板类名 是一致的
public T ShowPanel<T>(string packageName) where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果字典中有该面板的名字 证明已经创建过了 直接返回即可
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].visible = true;
return panelDic[panelName] as T;
}
//加载包和依赖包
//由于从Resources文件夹中加载包 会帮助我们判断重复没有 所以 这里既是重复执行也没什么问题
UIPackage package = UIPackage.AddPackage("UI/" + packageName);
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
//创建组件面板
GComponent panel = UIPackage.CreateObject(packageName, panelName).asCom;
//把组件的尺寸设置的和逻辑分辨率一致
panel.MakeFullScreen();
GRoot.inst.AddChild(panel);
//和父对象建立 宽高关联 这样 分辨率变化时 面板也不会出问题
panel.AddRelation(GRoot.inst, RelationType.Size);
//进行批处理 DC优化 开关开启
panel.fairyBatching = true;
//把当前显示的面板存起来 用于之后的隐藏
panelDic.Add(panelName, panel);
//把父类转换成对应的 子类
return panel as T;
}
//显示窗口方法
public T ShowWindow<T>() where T:Window,new()
{
Type type = typeof(T);
string windowName = type.Name;
//判断有没有面板
if (windowDic.ContainsKey(windowName))
{
windowDic[windowName].Show();
return windowDic[windowName] as T;
}
//创建并显示面板
T win = new T();
//记录字典中
windowDic.Add(windowName, win);
//当存储了再去显示 避免显示时调用隐藏不执行
win.Show();
return win;
}
public void HidePanel<T>(bool isDispose = false) where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果没有面板显示着 就直接返回
if (!panelDic.ContainsKey(panelName))
return;
//希望移除面板
if( isDispose )
{
//移除面板 并且从字典中移除
panelDic[panelName].Dispose();
panelDic.Remove(panelName);
}
//希望只是失活
else
{
panelDic[panelName].visible = false;
}
}
//隐藏窗口方法
public void HideWindow<T>(bool isDispose = false)
{
Type type = typeof(T);
string windowName = type.Name;
if (windowDic.ContainsKey(windowName))
{
if(isDispose)
{
windowDic[windowName].Dispose();
windowDic.Remove(windowName);
}
else
{
windowDic[windowName].Hide();
}
}
}
public T GetPanel<T>() where T:GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果有这个面板 直接返回
if (panelDic.ContainsKey(panelName))
return panelDic[panelName] as T;
return null;
}
//得到窗口
public T GetWindow<T>() where T:Window
{
Type type = typeof(T);
string windowName = type.Name;
if (windowDic.ContainsKey(windowName))
{
return windowDic[windowName] as T;
}
return null;
}
//主要用于销毁所有面板 和 资源垃圾回收的方法
public void ClearPanel(bool isGC = false)
{
//销毁所有面板 并且清空字典
foreach (var item in panelDic.Values)
{
item.Dispose();
}
panelDic.Clear();
if(isGC)
{
//释放所有包资源
UIPackage.RemoveAllPackages();
//垃圾回收
GC.Collect();
}
}
//清除所有窗口
public void ClearWindow(bool isGC = false)
{
//销毁所有面板 并且清空字典
foreach (var item in windowDic.Values)
{
item.Dispose();
}
windowDic.Clear();
if(isGC)
{
//释放所有包资源
UIPackage.RemoveAllPackages();
//垃圾回收
GC.Collect();
}
}
/// <summary>
/// 加载组件
/// </summary>
/// <param name="packageName">包名</param>
/// <param name="componentName">组件名</param>
/// <returns></returns>
public GComponent LoadComponent(string packageName, string componentName)
{
//加载包
UIPackage package = UIPackage.AddPackage("UI/" + packageName);
//加载依赖包
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
GComponent component = UIPackage.CreateObject(packageName, componentName).asCom;
//component.MakeFullScreen();
//优化dc,只需要把面板组件fairyBatching设置为true
component.fairyBatching = true;
return component;
}
}
BinaryDataMgr
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
/// <summary>
/// 2进制数据管理器
/// </summary>
public class BinaryDataMgr
{
/// <summary>
/// 2进制数据存储位置路径
/// </summary>
public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Binary/";
/// <summary>
/// 用于存储所有Excel表数据的容器
/// </summary>
private Dictionary<string, object> tableDic = new Dictionary<string, object>();
/// <summary>
/// 数据存储的位置
/// </summary>
private static string SAVE_PATH = Application.persistentDataPath + "/Data/";
private static BinaryDataMgr instance = new BinaryDataMgr();
public static BinaryDataMgr Instance => instance;
private BinaryDataMgr()
{
InitData();
}
public void InitData()
{
LoadTable<ServerInfoContainer, ServerInfo>();
}
/// <summary>
/// 加载Excel表的2进制数据到内存中
/// </summary>
/// <typeparam name="T">容器类名</typeparam>
/// <typeparam name="K">数据结构类类名</typeparam>
public void LoadTable<T,K>()
{
//读取 excel表对应的2进制文件 来进行解析
using (FileStream fs = File.Open(DATA_BINARY_PATH + typeof(K).Name + ".tao", FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
fs.Close();
//用于记录当前读取了多少字节了
int index = 0;
//读取多少行数据
int count = BitConverter.ToInt32(bytes, index);
index += 4;
//读取主键的名字
int keyNameLength = BitConverter.ToInt32(bytes, index);
index += 4;
string keyName = Encoding.UTF8.GetString(bytes, index, keyNameLength);
index += keyNameLength;
//创建容器类对象
Type contaninerType = typeof(T);
object contaninerObj = Activator.CreateInstance(contaninerType);
//得到数据结构类的Type
Type classType = typeof(K);
//通过反射 得到数据结构类 所有字段的信息
FieldInfo[] infos = classType.GetFields();
//读取每一行的信息
for (int i = 0; i < count; i++)
{
//实例化一个数据结构类 对象
object dataObj = Activator.CreateInstance(classType);
foreach (FieldInfo info in infos)
{
if( info.FieldType == typeof(int) )
{
//相当于就是把2进制数据转为int 然后赋值给了对应的字段
info.SetValue(dataObj, BitConverter.ToInt32(bytes, index));
index += 4;
}
else if (info.FieldType == typeof(float))
{
info.SetValue(dataObj, BitConverter.ToSingle(bytes, index));
index += 4;
}
else if (info.FieldType == typeof(bool))
{
info.SetValue(dataObj, BitConverter.ToBoolean(bytes, index));
index += 1;
}
else if (info.FieldType == typeof(string))
{
//读取字符串字节数组的长度
int length = BitConverter.ToInt32(bytes, index);
index += 4;
info.SetValue(dataObj, Encoding.UTF8.GetString(bytes, index, length));
index += length;
}
}
//读取完一行的数据了 应该把这个数据添加到容器对象中
//得到容器对象中的 字典对象
object dicObject = contaninerType.GetField("dataDic").GetValue(contaninerObj);
//通过字典对象得到其中的 Add方法
MethodInfo mInfo = dicObject.GetType().GetMethod("Add");
//得到数据结构类对象中 指定主键字段的值
object keyValue = classType.GetField(keyName).GetValue(dataObj);
mInfo.Invoke(dicObject, new object[] { keyValue, dataObj });
}
//把读取完的表记录下来
tableDic.Add(typeof(T).Name, contaninerObj);
fs.Close();
}
}
/// <summary>
/// 得到一张表的信息
/// </summary>
/// <typeparam name="T">容器类名</typeparam>
/// <returns></returns>
public T GetTable<T>() where T:class
{
string tableName = typeof(T).Name;
if (tableDic.ContainsKey(tableName))
return tableDic[tableName] as T;
return null;
}
/// <summary>
/// 存储类对象数据
/// </summary>
/// <param name="obj"></param>
/// <param name="fileName"></param>
public void Save(object obj, string fileName)
{
//先判断路径文件夹有没有
if (!Directory.Exists(SAVE_PATH))
Directory.CreateDirectory(SAVE_PATH);
using (FileStream fs = new FileStream(SAVE_PATH + fileName + ".tao", FileMode.OpenOrCreate, FileAccess.Write))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, obj);
fs.Close();
}
}
/// <summary>
/// 读取2进制数据转换成对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName"></param>
/// <returns></returns>
public T Load<T>(string fileName) where T:class
{
//如果不存在这个文件 就直接返回泛型对象的默认值
if( !File.Exists(SAVE_PATH + fileName + ".tao") )
return default(T);
T obj;
using (FileStream fs = File.Open(SAVE_PATH + fileName + ".tao", FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
obj = bf.Deserialize(fs) as T;
fs.Close();
}
return obj;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com