diff --git a/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs b/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs
new file mode 100644
index 00000000..dffeecac
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs
@@ -0,0 +1,300 @@
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngineInternal;
+using Object = UnityEngine.Object;
+
+namespace TEngine.Runtime
+{
+ ///
+ /// 封装Unity相关的一些通用接口
+ ///
+ public class UnityUtil
+ {
+ [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]
+ public static Component AddMonoBehaviour(Type type, GameObject go)
+ {
+ var comp = go.GetComponent(type);
+ if (comp == null)
+ {
+ comp = go.AddComponent(type);
+ }
+
+ return comp;
+ }
+
+ public static T AddMonoBehaviour(Component comp) where T : Component
+ {
+ var ret = comp.GetComponent();
+ if (ret == null)
+ {
+ ret = comp.gameObject.AddComponent();
+ }
+
+ return ret;
+ }
+
+ public static T AddMonoBehaviour(GameObject go) where T : Component
+ {
+ var comp = go.GetComponent();
+ if (comp == null)
+ {
+ comp = go.AddComponent();
+ }
+
+ return comp;
+ }
+
+ [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]
+ public static void RmvMonoBehaviour(Type type, GameObject go)
+ {
+ var comp = go.GetComponent(type);
+ if (comp != null)
+ {
+ UnityEngine.Object.Destroy(comp);
+ }
+ }
+
+ public static void RmvMonoBehaviour(GameObject go) where T : Component
+ {
+ var comp = go.GetComponent();
+ if (comp != null)
+ {
+ UnityEngine.Object.Destroy(comp);
+ }
+ }
+
+
+ public static Transform FindChild(Transform transform, string path)
+ {
+ var findTrans = transform.Find(path);
+ if (findTrans != null)
+ {
+ return findTrans;
+ }
+
+ return null;
+ }
+
+ public static Transform FindChildByName(Transform transform, string name)
+ {
+ if (transform == null)
+ {
+ return null;
+ }
+
+ for (int i = 0; i < transform.childCount; i++)
+ {
+ var childTrans = transform.GetChild(i);
+ if (childTrans.name == name)
+ {
+ return childTrans;
+ }
+
+ var find = FindChildByName(childTrans, name);
+ if (find != null)
+ {
+ return find;
+ }
+ }
+
+ return null;
+ }
+
+ [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]
+ public static Component FindChildComponent(Type type, Transform transform, string path)
+ {
+ var findTrans = transform.Find(path);
+ if (findTrans != null)
+ {
+ return findTrans.gameObject.GetComponent(type);
+ }
+
+ return null;
+ }
+
+ public static T FindChildComponent(Transform transform, string path) where T : Component
+ {
+ var findTrans = transform.Find(path);
+ if (findTrans != null)
+ {
+ return findTrans.gameObject.GetComponent();
+ }
+
+ return null;
+ }
+
+ public static void SetLayer(GameObject go, int layer)
+ {
+ if (go == null)
+ {
+ return;
+ }
+
+ SetLayer(go.transform, layer);
+ }
+
+ public static void SetLayer(Transform trans, int layer)
+ {
+ if (trans == null)
+ {
+ return;
+ }
+
+ trans.gameObject.layer = layer;
+ for (int i = 0, imax = trans.childCount; i < imax; ++i)
+ {
+ Transform child = trans.GetChild(i);
+ SetLayer(child, layer);
+ }
+ }
+
+ public static int RandomRangeInt(int min, int max)
+ {
+ return UnityEngine.Random.Range(min, max);
+ }
+
+ public static float RandomRangeFloat(float min, float max)
+ {
+ return UnityEngine.Random.Range(min, max);
+ }
+
+ public static Vector2 RandomInsideCircle(float radius)
+ {
+ return UnityEngine.Random.insideUnitCircle * radius;
+ }
+
+ [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]
+ public static Array CreateUnityArray(Type type, int length)
+ {
+ return Array.CreateInstance(type, length);
+ }
+
+ public static T[] CreateUnityArray(int length)
+ {
+ return new T[length];
+ }
+
+
+ public static GameObject Instantiate(GameObject go)
+ {
+ if (go != null)
+ {
+ return UnityEngine.GameObject.Instantiate(go);
+ }
+
+ return null;
+ }
+
+ public static int GetHashCodeByString(string str)
+ {
+ return str.GetHashCode();
+ }
+
+ public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask)
+ {
+ return Physics.Raycast(ray, out hitInfo, maxDistance, layerMask);
+ }
+
+ public static List GetRegexMatchGroups(string pattern, string input)
+ {
+ List list = new List();
+ var regexLink = new Regex(pattern);
+ var links = regexLink.Match(input);
+ for (var i = 0; i < links.Groups.Count; ++i)
+ {
+ list.Add(links.Groups[i].Value);
+ }
+
+ return list;
+ }
+
+ public static void SetMaterialVector3(Material mat, int nameId, Vector3 val)
+ {
+ mat.SetVector(nameId, val);
+ }
+
+ public static void GetVectorData(Vector3 val, out float x, out float y, out float z)
+ {
+ x = val.x;
+ y = val.y;
+ z = val.z;
+ }
+
+ public static void GetVector2Data(Vector2 val, out float x, out float y)
+ {
+ x = val.x;
+ y = val.y;
+ }
+
+ public static bool GetTouchByFingerId(int fingerId, out Touch findTouch)
+ {
+ var finded = false;
+ var touchCnt = Input.touchCount;
+
+ findTouch = new Touch();
+ for (int i = 0; i < touchCnt; i++)
+ {
+ var touch = Input.GetTouch(i);
+ if (touch.fingerId == fingerId)
+ {
+ findTouch = touch;
+ finded = true;
+ break;
+ }
+ }
+
+ return finded;
+ }
+
+ public static bool SetAnimatorController(GameObject go, string resPath)
+ {
+ //RuntimeAnimatorController rac = (RuntimeAnimatorController)ResourcesManager.Instance.Load(resPath);
+ //if (rac == null)
+ //{
+ // Debug.Log("GetAnimator failed path: " + resPath);
+ // return false;
+ //}
+
+ //var ani = go.GetComponentInChildren(true);
+
+ //if (ani != null)
+ //{
+ // ani.runtimeAnimatorController = rac;
+ // return true;
+ //}
+
+ return false;
+ }
+
+ public static void SetGameObjectActive(GameObject go, bool active)
+ {
+ if (go != null && go.activeSelf != active)
+ {
+ go.SetActive(active);
+ }
+ }
+
+ public static T[] GetComponentsInChildren(GameObject go) where T : UIBehaviour
+ {
+ if (go != null)
+ {
+ return go.GetComponentsInChildren();
+ }
+
+ return null;
+ }
+
+ public static T GetComponent(GameObject go)
+ {
+ if (go != null)
+ {
+ return go.GetComponent();
+ }
+
+ return default(T);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs.meta b/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs.meta
new file mode 100644
index 00000000..b4427d6b
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/Core/Utility/UnityUtil.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bdc9d542a7834f14881e0b0ea544ca01
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/UIModule/Scripts.meta b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts.meta
new file mode 100644
index 00000000..3f2daf29
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4730d132ebcf0b34a94c75287e582f9a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr.meta b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr.meta
new file mode 100644
index 00000000..2a2eb77a
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 144caac249909404f9af09b2998611b8
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs
new file mode 100644
index 00000000..a54614e4
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs
@@ -0,0 +1,7 @@
+namespace TEngine.Runtime.UIModule
+{
+ public interface IUIController
+ {
+ void RegisterUIEvent();
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs.meta b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs.meta
new file mode 100644
index 00000000..63a1e063
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/IUIController.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0801c753191b47a08c37d1f5dd82e38b
+timeCreated: 1661502732
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/UIManager.cs b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/UIManager.cs
new file mode 100644
index 00000000..f64ac417
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/UIModule/Scripts/Mgr/UIManager.cs
@@ -0,0 +1,533 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+namespace TEngine.Runtime.UIModule
+{
+ public sealed partial class UIManager : TSingleton
+ {
+ private Transform m_canvasTrans;
+ public Canvas m_canvas;
+ private Dictionary m_allWindow = new Dictionary();
+
+ ///
+ /// 不同显示顺序的的窗口列表
+ ///
+ private UIWindowStack[] m_listWindowStack = new UIWindowStack[(int)WindowStackIndex.StackMax];
+
+ ///
+ /// 类型到实例的索引
+ ///
+ private static Dictionary m_typeToInst = new Dictionary();
+
+ ///
+ /// 类型和资源的绑定关系
+ ///
+ private Dictionary m_uiType2PrefabPath = new Dictionary();
+
+ private GameObject m_uiManagerGo;
+ private Transform m_uiManagerTransform;
+ private Camera m_uiCamera;
+ public Camera Camera => m_uiCamera;
+
+ public UIManager()
+ {
+ m_uiManagerGo = TResources.Load("UI/UIRoot.prefab");
+ Object.DontDestroyOnLoad(m_uiManagerGo);
+ m_uiManagerTransform = m_uiManagerGo.transform;
+ m_uiCamera = UnityUtil.FindChildComponent(m_uiManagerTransform, "Camera");
+ Canvas canvas = m_uiManagerGo.GetComponentInChildren