EGUI框架,包括dotween,util,Editor一套完整框架
链接:https://pan.baidu.com/s/1Dq_ySDsWbdmUHmEs0Vb0lw
提取码:wtbc
框架就一个脚本 UIPage.cs,如下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace EG
{
public class UIPage : MonoBehaviour
{
#region static
private static bool isInit;
public static GameObject root;
public static GameObject normalNode;
public static GameObject fixedNode;
public static GameObject popupNode;
public static Camera uiCamera;
//public static AudioListener uiAudioListener;
public static EventSystem eventSystem;
public static Canvas canvas;
public static CanvasScaler canvasScaler;
public static GraphicRaycaster graphicRaycaster;
public static float screenWidth = 1920;
public static float screenHeight = 1080;
private static bool isPortrait;
public static AllPages allPages;
#endregion
#region member
public string uiPath;
public string pageName;
public UIType uiType;
public UIData uiData;
#endregion
private static void Init()
{
root = new GameObject("Root");
DontDestroyOnLoad(root);
root.transform.position = Vector3.zero;
normalNode = new GameObject("NormalNode");
normalNode.transform.SetParent(root.transform);
normalNode.transform.localPosition = Vector3.zero;
fixedNode = new GameObject("FixedNode");
fixedNode.transform.SetParent(root.transform);
fixedNode.transform.localPosition = Vector3.zero;
popupNode = new GameObject("PopupNode");
popupNode.transform.SetParent(root.transform);
popupNode.transform.localPosition = Vector3.zero;
uiCamera = new GameObject("UICamera").AddComponent<Camera>();
uiCamera.transform.SetParent(root.transform);
uiCamera.transform.localPosition = Vector3.zero;
eventSystem = new GameObject("EventSystem").AddComponent<EventSystem>();
eventSystem.transform.SetParent(root.transform);
eventSystem.transform.localPosition = Vector3.zero;
canvas = root.AddComponent<Canvas>();
canvasScaler = root.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
graphicRaycaster = root.AddComponent<GraphicRaycaster>();
//uiAudioListener = uiCamera.gameObject.AddComponent<AudioListener>();
uiCamera.clearFlags = CameraClearFlags.Depth;
uiCamera.cullingMask = 1 << LayerMask.NameToLayer("UI");
// //相机打开Defalut层
// uiCamera.cullingMask |= (1 << 0);
//
uiCamera.orthographic = true;
uiCamera.transform.localPosition = Vector3.back * 1500;
canvas.renderMode = RenderMode.ScreenSpaceCamera;
canvas.worldCamera = uiCamera;
RectTransform nrf = normalNode.AddComponent<RectTransform>();
RectTransform frf = fixedNode.AddComponent<RectTransform>();
RectTransform prf = popupNode.AddComponent<RectTransform>();
nrf.sizeDelta = new Vector2(screenWidth, screenHeight);
frf.sizeDelta = new Vector2(screenWidth, screenHeight);
prf.sizeDelta = new Vector2(screenWidth, screenHeight);
root.layer = LayerMask.NameToLayer("UI");
normalNode.layer = LayerMask.NameToLayer("UI");
fixedNode.layer = LayerMask.NameToLayer("UI");
popupNode.layer = LayerMask.NameToLayer("UI");
eventSystem.gameObject.AddComponent<StandaloneInputModule>();
allPages = new AllPages();
isPortrait = screenWidth < screenHeight;
if (isPortrait)
{
ChangeToPortrait();
}
else
{
ChangeToLandscape();
}
isInit = true;
}
public static T ShowPage<T>(UIData data = null) where T : UIPage, new()
{
if (!isInit)
{
Init();
}
T t = new T();
if (allPages.ContainsKey(typeof(T).ToString()))
{
T pg = (T) allPages[typeof(T).ToString()];
pg.uiData = data;
pg.OnShowPage();
UIPage curPage = allPages.GetCurPage(pg.uiType);
if (curPage != null && curPage != pg)
{
curPage.OnLostFocusPage();
}
allPages.SetAsLastSibling(pg.pageName);
if (!pg.gameObject.activeSelf)
{
pg.OnActive();
}
return pg;
}
t.InitPage();
GameObject prefab = Resources.Load<GameObject>(t.uiPath);
T page = Instantiate(prefab).AddComponent<T>();
page.InitPage();
page.name = typeof(T).ToString();
page.pageName = typeof(T).ToString();
allPages.AddPage(page);
page.uiData = data;
#region MyRegion
RectTransform rectTransform = page.GetComponent<RectTransform>();
Vector3 anchorPos = Vector3.zero;
Vector3 scale = Vector3.one;
Vector2 sizeDel = Vector2.zero;
if (rectTransform != null)
{
anchorPos = rectTransform.anchoredPosition;
scale = rectTransform.localScale;
sizeDel = rectTransform.sizeDelta;
}
else
{
scale = page.transform.localScale;
}
if (page.uiType == UIType.Normal)
{
page.transform.SetParent(normalNode.transform);
}
else if (page.uiType == UIType.Fixed)
{
page.transform.SetParent(fixedNode.transform);
}
else if (page.uiType == UIType.PopUp)
{
page.transform.SetParent(popupNode.transform);
}
if (rectTransform != null)
{
rectTransform.anchoredPosition = anchorPos;
rectTransform.localScale = scale;
rectTransform.sizeDelta = sizeDel;
}
else
{
page.transform.localScale = scale;
page.transform.localPosition = Vector3.zero;
}
#endregion
page.OnShowPage();
UIPage curPage2 = allPages.GetCurPage(page.uiType);
if (curPage2 != null && curPage2 != page)
{
curPage2.OnLostFocusPage();
}
page.OnActive();
return page;
}
public static void ClosePage<T>() where T : UIPage, new()
{
if (!isInit)
{
Init();
}
T t = new T();
t.InitPage();
if (allPages.ContainsKey(typeof(T).ToString()))
{
T pg = (T) allPages[typeof(T).ToString()];
pg.OnClosePage();
if (pg.gameObject.activeSelf)
{
pg.OnHide();
}
UIPage curPage = allPages.GetCurPage(pg.uiType);
if (curPage != null && curPage != pg)
{
curPage.OnFocusPage();
}
}
else
{
Debug.LogWarning("no page named \"" + typeof(T) + "\"");
}
}
public static void CloseCurPage(UIType uiType)
{
UIPage page = allPages.GetCurPage(uiType);
if (page != null)
{
if (!isInit)
{
Init();
}
page.OnClosePage();
if (page.gameObject.activeSelf)
{
page.OnHide();
}
UIPage curPage = allPages.GetCurPage(page.uiType);
if (curPage != null && curPage != page)
{
curPage.OnFocusPage();
}
}
}
public static void ChangeToLandscape()
{
if (isPortrait)
{
canvasScaler.referenceResolution = new Vector2(screenHeight, screenWidth);
canvasScaler.matchWidthOrHeight = 1;
Screen.orientation = ScreenOrientation.Landscape;
}
else
{
canvasScaler.referenceResolution = new Vector2(screenWidth, screenHeight);
canvasScaler.matchWidthOrHeight = 1;
Screen.orientation = ScreenOrientation.Landscape;
}
}
public static void ChangeToPortrait()
{
if (isPortrait)
{
canvasScaler.referenceResolution = new Vector2(screenWidth, screenHeight);
canvasScaler.matchWidthOrHeight = 0;
Screen.orientation = ScreenOrientation.Portrait;
}
else
{
canvasScaler.referenceResolution = new Vector2(screenHeight, screenWidth);
canvasScaler.matchWidthOrHeight = 0;
Screen.orientation = ScreenOrientation.Portrait;
}
}
public virtual void InitPage()
{
}
public virtual void OnShowPage()
{
}
public virtual void OnClosePage()
{
}
public virtual void OnFocusPage()
{
}
public virtual void OnLostFocusPage()
{
}
public virtual void OnActive()
{
gameObject.SetActive(true);
}
public virtual void OnHide()
{
gameObject.SetActive(false);
}
public bool IsOnGUI
{
get
{
PointerEventData eventData = new PointerEventData(EventSystem.current);
eventData.pressPosition = Input.mousePosition;
eventData.position = Input.mousePosition;
List<RaycastResult> list = new List<RaycastResult>();
graphicRaycaster.Raycast(eventData, list);
return list.Count > 0;
}
}
}
public enum UIType
{
Normal,
Fixed,
PopUp,
None,
}
public class AllPages
{
private List<UIPage> allPages;
public UIPage this[int index]
{
get { return allPages[index]; }
}
public UIPage this[string pageName]
{
get
{
foreach (var uiPage in allPages)
{
if (uiPage.pageName == pageName)
{
return uiPage;
}
}
throw new KeyNotFoundException("the ui which has a name called \"" + pageName + "\" can not be found!");
}
}
public void AddPage(UIPage page)
{
if (allPages == null)
{
allPages = new List<UIPage>();
}
foreach (var uiPage in allPages)
{
if (uiPage.pageName == page.pageName)
{
throw new Exception("has already add a page which called \"" + page.pageName + "\"!");
}
}
allPages.Add(page);
}
public bool ContainsKey(string pageName)
{
if (allPages == null)
{
allPages = new List<UIPage>();
}
foreach (var uiPage in allPages)
{
if (uiPage.pageName == pageName)
{
return true;
}
}
return false;
}
public void SetAsLastSibling(string pageName)
{
var temp = this[pageName];
allPages.Remove(this[pageName]);
this.AddPage(temp);
temp.transform.SetAsLastSibling();
}
public UIPage GetCurPage(UIType uiType)
{
for (int i = allPages.Count - 1; i >= 0; i--)
{
if (allPages[i].gameObject.activeSelf && allPages[i].uiType == uiType)
{
return allPages[i];
}
}
return null;
}
}
public class UIData
{
public object data;
public Action cb;
}
}
下面是代码创建工具,不需要手写QuitUI里初始化代码,只需要工具生成
1.把该工具代码放在Editor文件夹下。工具如下
EGUIScriptCreator.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Experimental.UIElements;
using UnityEngine;
using UnityEngine.UI;
public class EGUIScriptCreator : EditorWindow
{
private List<ToggleData> _toggleDatas;
private GameObject curSelectGo;
private string titleTxt;
private string[] compTypeArr = new[]
{
"Button", "InputField", "Toggle", "ToggleGroup", "Slider", "ScrollRect",
"Scrollbar", "Image", "Text", "RawImage",
"Transform", "RectTransform", "GameObject"
};
private string[] windowTypeArr = new[] {"Normal", "Fixed", "Popup"};
private string[] AnimionTypeArr = new[] {"Drop", "LeftOut", "RightOut", "CenterScale", "None"};
private ClassData _classData;
private Dictionary<string, ToggleData> _dictionary;
private List<string> tweenOptions = new List<string>();
private int tweenIndex = 0;
private string tweenObjectName = "";
private Vector2 scroPos;
private string createPath = "Assets/Script/UI";
[MenuItem("EGTools/EGUIScriptCreator")]
static void Init()
{
GetWindow<EGUIScriptCreator>().titleContent =
new GUIContent("EGUIScriptCreator", Resources.Load<Texture>("Icon/eg"));
}
private void OnGUI()
{
scroPos = GUILayout.BeginScrollView(scroPos, GUILayout.Width(position.width),
GUILayout.Height(position.height));
GUILayout.Label(titleTxt);
if (_toggleDatas != null)
{
ShowToggle(_toggleDatas);
GUILayout.Label("\n================================================================\n");
GUILayout.Label("WindowType");
_classData.wtype =
(WindowType) GUILayout.SelectionGrid((int) _classData.wtype, windowTypeArr, windowTypeArr.Length);
ShowTweenPopup();
GUILayout.Label("AnimationType");
_classData.anim =
(Anim) GUILayout.SelectionGrid((int) _classData.anim, AnimionTypeArr, AnimionTypeArr.Length);
GUILayout.Label("\n================================================================\n");
GUILayout.Label("生成位置:");
createPath = GUILayout.TextField(createPath);
if (GUILayout.Button("生成"))
{
if (!Directory.Exists(createPath))
{
Directory.CreateDirectory(createPath);
AssetDatabase.Refresh();
}
GenerateCode();
}
}
GUILayout.EndScrollView();
}
private void GenerateCode()
{
List<ToggleData> temp = new List<ToggleData>();
GetToggleData(_toggleDatas, temp);
foreach (var toggleData in temp)
{
if (toggleData.isSelect)
{
string pro = "private " + toggleData.ctype + " " + toggleData.name + ";";
_classData.propertys.Add(pro);
string awa = toggleData.name + " = gameObject.transform.Find(\"" + toggleData.path + "\")";
if (toggleData.ctype != CompType.Transform && toggleData.ctype != CompType.GameObject)
{
awa += ".GetComponent<" + toggleData.ctype + ">();";
}
else if (toggleData.ctype == CompType.GameObject)
{
awa += ".gameObject;";
}
else
{
awa += ";";
}
_classData.awakes.Add(awa);
if (toggleData.ctype == CompType.Button)
{
string btnAdd = toggleData.name + ".onClick.AddListener(" + toggleData.name + "Click);";
_classData.awakes.Add(btnAdd);
string btnClick = "private void " + toggleData.name + "Click()\n {\n\n }";
_classData.btnEvents.Add(btnClick);
}
}
}
string classDataStr = "using System.Collections;\n" +
"using System.Collections.Generic;\n" +
"using EG;\n" +
"using DG.Tweening;\n" +
"using UnityEngine;\n" +
"using UnityEngine.UI;\n\n" +
"public class " + curSelectGo.name + " : UIPage\n" +
"{\n";
foreach (var classDataProperty in _classData.propertys)
{
classDataStr += " " + classDataProperty + "\n";
}
classDataStr += " public override void InitPage()\n" +
" {\n" +
" uiPath = \"UI/" + curSelectGo.name + "\";\n" +
" uiType = UIType." + _classData.wtype + ";\n" +
" }\n\n";
classDataStr += " public void Awake()\n" +
" {\n";
foreach (var classDataAwake in _classData.awakes)
{
classDataStr += " " + classDataAwake + "\n";
}
classDataStr += " }\n";
classDataStr += " public override void OnShowPage()\n" +
" {\n\n" +
" }\n\n";
classDataStr += " public override void OnClosePage()\n" +
" {\n\n" +
" }\n\n";
classDataStr += " public override void OnFocusPage()\n" +
" {\n\n" +
" }\n\n";
classDataStr += " public override void OnLostFocusPage()\n" +
" {\n\n" +
" }\n\n";
string animData = GetAnimData(_classData.anim);
classDataStr += animData;
foreach (var classDataBtnEvent in _classData.btnEvents)
{
classDataStr += classDataBtnEvent + "\n\n";
}
classDataStr += "}";
if (File.Exists(Path.Combine(createPath, curSelectGo.name + ".cs")))
{
Debug.LogError("文件【" + Path.Combine(createPath, curSelectGo.name) + "】已存在!无法生成!");
}
else
{
FileInfo fileInfo = new FileInfo(Path.Combine(createPath, curSelectGo.name + ".cs"));
StreamWriter streamWriter = fileInfo.CreateText();
streamWriter.WriteLine(classDataStr);
streamWriter.Close();
AssetDatabase.Refresh();
}
}
private string GetAnimData(Anim anim)
{
if (anim == Anim.None)
{
return "";
}
string data = Resources.Load<TextAsset>("AnimTxt/" + anim).text;
data = data.Replace("__obj", tweenObjectName);
return data;
}
private void ShowTweenPopup()
{
if (_toggleDatas != null && _toggleDatas.Count > 0)
{
List<ToggleData> temp = new List<ToggleData>();
tweenOptions.Clear();
GetToggleData(_toggleDatas, temp);
tweenOptions.Add("gameObject");
foreach (var toggleData in temp)
{
tweenOptions.Add(toggleData.path);
}
GUILayout.Label("");
GUILayout.Label("===================================================");
GUILayout.Label("请选择动画作用对象");
if (tweenIndex >= tweenOptions.Count - 1)
{
tweenIndex = 0;
}
tweenIndex = EditorGUILayout.Popup(tweenIndex, tweenOptions.ToArray());
tweenObjectName = tweenIndex == 0 ? "gameObject" : temp[tweenIndex - 1].name;
}
}
private void GetToggleData(List<ToggleData> toggleDatas, List<ToggleData> outToggleDatas)
{
foreach (var toggleData in toggleDatas)
{
outToggleDatas.Add(toggleData);
GetToggleData(toggleData.child, outToggleDatas);
}
}
private T GetCompInParent<T>(Transform tr) where T : Component
{
if (tr == null)
{
return null;
}
T t = tr.GetComponent<T>();
if (t != null)
{
return t;
}
return GetCompInParent<T>(tr.parent);
}
private void GetToggleData(List<ToggleData> toggleDatas, GameObject root, string parentPath = "")
{
foreach (Transform tr in root.transform)
{
string tempPath = parentPath == "" ? "" : parentPath + "/";
string thisPath = tempPath + tr.name;
string proName = GetName(tr.name.Replace("(", "").Replace(")", "").Replace(" ", ""));
ToggleData thisData = new ToggleData
{
isSelect = true,
path = thisPath,
child = new List<ToggleData>(),
name = proName
};
if (tr.name == "Background")
{
Debug.Log(tr.GetComponentInParent<Toggle>());
}
_dictionary.Add(proName, thisData);
if (tr.GetComponent<Button>() != null)
{
thisData.ctype = CompType.Button;
}
else if (tr.GetComponent<InputField>() != null)
{
thisData.ctype = CompType.InputField;
}
else if (tr.GetComponent<Slider>() != null)
{
thisData.ctype = CompType.Slider;
}
else if (tr.GetComponent<Toggle>() != null)
{
thisData.ctype = CompType.Toggle;
}
else if (tr.GetComponent<ToggleGroup>() != null)
{
thisData.ctype = CompType.ToggleGroup;
}
else if (tr.GetComponent<ScrollRect>() != null)
{
thisData.ctype = CompType.ScrollRect;
}
else if (tr.GetComponent<Scrollbar>() != null)
{
thisData.ctype = CompType.Scrollbar;
}
else if (tr.GetComponent<Text>() != null)
{
thisData.ctype = CompType.Text;
}
else if (tr.GetComponent<RawImage>() != null)
{
thisData.ctype = CompType.RawImage;
}
else if (tr.GetComponent<Image>() != null)
{
thisData.ctype = CompType.Image;
}
else
{
thisData.ctype = CompType.Transform;
}
if ((thisData.ctype != CompType.Button && GetCompInParent<Button>(tr) != null) ||
(thisData.ctype != CompType.Slider && GetCompInParent<Slider>(tr) != null) ||
(thisData.ctype != CompType.InputField && GetCompInParent<InputField>(tr) != null) ||
(thisData.ctype != CompType.Toggle && GetCompInParent<Toggle>(tr) != null) ||
(thisData.ctype != CompType.ScrollRect && GetCompInParent<ScrollRect>(tr) != null &&
tr.parent.GetComponent<Mask>() == null) ||
(thisData.ctype != CompType.Scrollbar && GetCompInParent<Scrollbar>(tr) != null))
{
thisData.isSelect = false;
}
toggleDatas.Add(thisData);
GetToggleData(thisData.child, tr.gameObject, thisPath);
}
}
private void ShowToggle(List<ToggleData> toggleDatas)
{
foreach (var toggleData in toggleDatas)
{
toggleData.isSelect = GUILayout.Toggle(toggleData.isSelect, toggleData.path);
toggleData.ctype =
(CompType) GUILayout.SelectionGrid((int) toggleData.ctype, compTypeArr, compTypeArr.Length);
ShowToggle(toggleData.child);
}
}
private string GetName(string name)
{
string temp = name;
int n = 1;
while (true)
{
if (_dictionary.ContainsKey(temp))
{
temp = name + n;
n++;
}
else
{
break;
}
}
return temp;
}
private void OnSelectionChange()
{
if (curSelectGo != Selection.activeGameObject)
{
curSelectGo = null;
_toggleDatas = null;
_classData = null;
_dictionary = null;
tweenOptions.Clear();
}
if (Selection.activeGameObject != null && Selection.activeGameObject != curSelectGo)
{
curSelectGo = Selection.activeGameObject;
_toggleDatas = new List<ToggleData>();
_classData = new ClassData();
_dictionary = new Dictionary<string, ToggleData>();
GetToggleData(_toggleDatas, curSelectGo);
}
if (_toggleDatas == null)
{
titleTxt = "请先选择一个预制体";
}
else if (curSelectGo != null)
{
titleTxt = "以下是UI预制体" + curSelectGo.name +
"子物体选项\n================================================================";
}
}
private void OnInspectorUpdate()
{
Repaint();
OnSelectionChange();
}
}
public class ToggleData
{
public string name;
public bool isSelect;
public string path;
public List<ToggleData> child;
public CompType ctype;
}
public enum CompType
{
Button,
InputField,
Toggle,
ToggleGroup,
Slider,
ScrollRect,
Scrollbar,
Image,
Text,
RawImage,
Transform,
RectTransform,
GameObject
}
public class ClassData
{
public List<string> propertys;
public List<string> awakes;
public List<string> btnEvents;
public WindowType wtype;
public Anim anim;
public ClassData()
{
propertys = new List<string>();
awakes = new List<string>();
btnEvents = new List<string>();
}
}
public enum WindowType
{
Normal,
Fixed,
PopUp
}
public enum Anim
{
Drop,
LeftOut,
RightOut,
CenterScale,
None
}
2.使用:
选中创建好的预制体,选择EGTools/EGUIScriptCreator,勾选需要赋值的button或者Image等等。。,完毕后生成。自动生成脚本到Scripts/UI文件夹下,并且已经对预制体上的组件进行赋值。按钮也添加好了事件。
下面是工具创建好的UI代码,打开QuitUI后在QuitUI里执行的方法
每个UI脚本调用 ,并继承UIPage, InitPage()初始化,uiPath:ui预制体的路径,uiType :弹出形式
例如:
public override void InitPage()
{
uiPath = “UI/QuitUI”;
uiType = UIType.Normal;
}
下面完整UI界面代码:
using System.Collections;
using System.Collections.Generic;
using EG;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class QuitUI : UIPage
{
private Button YesBtn;//定义ui的组件
public override void InitPage()
{
uiPath = "UI/QuitUI";
uiType = UIType.Normal;
}
public void Awake()
{
//组件赋值
YesBtn = gameObject.transform.Find("bg/YesBtn").GetComponent<Button>();
YesBtn.onClick.AddListener(YesBtnClick);
}
public override void OnShowPage()
{
// modelObj = (GameObject) uiData.data;//在ShowPage时传的参数是什么类型,就强转什么类型
//当显示UI时执行的方法
}
public override void OnClosePage()
{
//当关闭UI时执行的方法
}
public override void OnFocusPage()
{
//当获取焦点时调用
}
public override void OnLostFocusPage()
{
//当失去焦点时调用
}
// 当enable为true时调用
public override void OnActive()
{
if (!gameObject.activeSelf)
{
base.OnActive();
}
}
//当隐藏时调用
public override void OnHide()
{
if (gameObject.activeSelf)
{
}
}
}
UI调用案例:
打开QuitUI方法 :
(1)打开UI不传参数: UIPage.ShowPage<QuitUI>();
(2) 打开UI传参数:
UIPage.ShowPage<QuitUI>(new UIData()
{
data= 要传的参数(任意类型) , cb = ()=> { //回调函数,可为空 }
});
例子:
打开UI时传递参数
private GameObject obj;
//打开UI界面
UIPage.ShowPage<FuncUI>(new UIData()
{
data=obj, cb = () =>{Debug.Log("这是回调函数");}
});
UI界面获取传过来的参数
//UI界面的OnShowPage方法里接收参数
public override void OnShowPage()
{
//uiData.data:上级界面传递过来的参数,(这里传的是GameObject)
GameObject modelObj = (GameObject) uiData.data;
}