using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using CaoCao.Runtime; using CaoCao.XAsset; using UnityEngine.EventSystems; using Game; public enum eUINodeType { NodeBg = 0, // 游戏根层显示, 主要用来显示背景贴图 NodeScreen, // 全屏UI, 比如主场景的主UI, 战斗场景战斗UI. NodeUI, // 功能UI等 NodeUIMidle, // 功能UI(中间层)等 以防止某些UI放于tip层 loading层的情况 NodeUITop, // 功能UI(最上层)等 以防止某些UI放于tip层 loading层的情况 NodeLoading, // 加载界面层 NodeTip, // 提示层 } /// /// 为了兼容异步加载的问题定义的数据结构 /// public class CustomUserData { public UIBase ui; public Type mType; public string uiName; public Transform tfParent; public AssetBundle descBundle; public object[] userData; } /// /// UIManager /// UI管理器 /// 常用方法: /// UIMgr.Instance.Open() 显示某个UI /// UIMgr.Instance.OpenInChild() 在某个结点下显示UI /// UIMgr.Instance.GetUI() 获取某个打开的UI实例 /// UIMgr.Instance.GetTopUI() 获取最外层UI /// UIMgr.Instance.Hide() 隐藏某个UI /// UIMgr.Instance.HideAll() 隐藏所有UI /// UIMgr.Instance.CloseUI() 销毁某个UI /// UIMgr.Instance.CloseUI(UIBase _ui) 销毁某个UI /// UIMgr.Instance.Clean() 销毁所有UI /// UIMgr.Instance.CleanExceptLoading() 销毁除LoadingUI外的所有UI /// UIMgr.Instance.MoveRootUp() 移动UI上下位置 /// public class UIMgr : GameComponent { public static UIMgr Instance; public static readonly string UIPrefabRootPath = "Assets/GameAssets/Prefabs/UI"; // UI Prefab根目录 public static readonly string UIPathConfigFile = "Assets/GameAssets/TextAssets/UIMgrPath.json"; // UI Prefab资源路径文件名 public Transform m_NodeBg; // 背景层 public Transform m_NodeScreen; // 全屏UI层, 比如主场景的主UI, 战斗场景战斗UI. 人物信息, 血条, 主界面的小地图等等 public Transform m_NodeUI; // UI层, 功能层. 比如强化, 宠物等 public Transform m_NodeUIMidle; // UI层, 功能层. 比如强化, 宠物等 功能UI,(中间层)等 以防止某些UI放于tip层 loading层的情况 public Transform m_NodeUITop; // UI层, 功能层. 比如强化, 宠物等 功能UI,(最上层)等 以防止某些UI放于tip层 loading层的情况 public Transform m_NodeLoading; // 加载界面层 public Transform m_NodeTip; // 弹窗提示层 public RectTransform m_RtfShelter; // 遮挡 用于4:3屏幕适配 private Transform m_NodeUIChildTop; // UI顶层 private static UIBase mTopUI; // 当前最外层UI private List _unAudioList; //不播放声音UI private static Dictionary m_UIDic; public static Dictionary UIDic { get { if (m_UIDic == null) m_UIDic = new Dictionary(); return m_UIDic; } } // 同步方式 保留 private static Dictionary m_AllUIPath; public static Dictionary AllUIPath { get { if (m_AllUIPath == null) { m_AllUIPath = new Dictionary(); m_AllUIPath = UIMgrPath.GetDic(); } return m_AllUIPath; } } public static Dictionary m_TypeParent; private RawImage m_imgBg; public Camera m_camera; public Canvas m_Canvas; public RectTransform m_CanvasRect; private bool m_isScreenClip; // 屏幕是否用黑边裁剪了 public bool IsScreenClip { get { return m_isScreenClip; } set { m_isScreenClip = true; } } //public Type hotResources = null; //private float _checkRemoveTime; protected override void Awake() { base.Awake(); Instance = this; //DontDestroyOnLoad(this); m_camera = transform.Find("Camera").GetComponent(); m_Canvas = transform.Find("Canvas").GetComponent(); m_CanvasRect = m_Canvas.GetComponent(); m_NodeBg = transform.Find("Canvas/NodeBg"); m_NodeScreen = transform.Find("Canvas/NodeScreen"); m_NodeUI = transform.Find("Canvas/NodeUI"); m_NodeUIMidle = transform.Find("Canvas/NodeUIMidle"); m_NodeUITop = transform.Find("Canvas/NodeUITop"); m_NodeLoading = transform.Find("Canvas/NodeLoading"); m_NodeTip = transform.Find("Canvas/NodeTip"); m_RtfShelter = transform.Find("Canvas/RtfShelter").GetComponent(); m_TypeParent = new Dictionary { {eUINodeType.NodeBg, m_NodeBg }, {eUINodeType.NodeScreen, m_NodeScreen }, {eUINodeType.NodeUI, m_NodeUI }, {eUINodeType.NodeUIMidle, m_NodeUIMidle }, {eUINodeType.NodeUITop, m_NodeUITop }, {eUINodeType.NodeTip, m_NodeTip }, {eUINodeType.NodeLoading, m_NodeLoading }, }; m_NodeUIChildTop = m_NodeUI.Find("Top"); m_imgBg = m_NodeBg.Find("imgBg").GetComponent(); _unAudioList = new List() { "LoginUI", "SelectPlayerUI", "CreatePlayerUI", "LoadingUI", "MiniMapUI", "SkillUI", "TeamAndTaskUI", "MainHeadUI", "MainExpUI", "MainChatUI", "TouchButtonEffectUI", "MainUI", "OtherHeadUI"}; ////PC还要过滤这几个UI,但仅PC加,减少手机过滤计算量 //if (HotfixEntry.IsPC) //{ // _unAudioList.AddRange(new List() { "ItemCommonPCHoverInfoUI", "TipsShowPCHoverUI", "TipsSkillPCHoverUI" }); //} } private void OnEnable() { //Inform.Listen(eInformId.SenceChange, CleanExceptLoading); } private void OnDisable() { //Inform.Cancel(eInformId.SenceChange, CleanExceptLoading); } #region OpenUI public void SetScalePr(UIBase ui) { //if (UICrossPlatform.IsNewPlan && HotfixEntry.IsPC) //{ // if (CheckIsScaleUI(ui)) // { // RectTransform rect = ui.GetComponent(); // float PC_ScalePr = UICrossPlatform.PC_ScalePr; // rect.localScale = new Vector3(PC_ScalePr, PC_ScalePr, PC_ScalePr); // Common.SetRectTransformSize(rect, Common.ScreenXY_Stand); // //pc模式下,添加拖拽逻辑 // PCUIDrag tt = rect.gameObject.GetComponent(); // if (tt == null) // { // tt = rect.gameObject.AddComponent(); // tt.SetDragTarget(rect); // rect.SetPivot2(PivotPresets.BottomLeft); // rect.SetAnchor(AnchorPresets.BottomLeft); // //位置设置 // if (ui is SplitRelevantUI) // { // rect.anchoredPosition3D = new Vector3(-350, 172, 0); // } // else // { // rect.anchoredPosition3D = new Vector3(116, 172, 0); // } // rect.sizeDelta = new Vector2(2778, 1284); // } // } //} ////手机 //else //{ // //非PC时且开启小宽高比手机适配方案 // if (UICrossPlatform.IsMobileNewPlan && UICrossPlatform.bMobileNeed) // { // if (CheckIsScaleUI(ui)) // { float Mobile_ScalePr = Common.GetUICrossPlatform_Mobile_ScalePr(); RectTransform rect = ui.GetComponent(); rect.localScale = new Vector3(Mobile_ScalePr, Mobile_ScalePr, Mobile_ScalePr); Common.SetRectTransformSize(rect, Common.ScreenXY_Stand); // } // } //} } public UIBase OpenUI(eUINodeType _layer = eUINodeType.NodeUI, params object[] _params) where T : UIBase { //Transform _tfParent = m_TypeParent[_layer]; //return OpenUIInChild(_tfParent, _params); Transform _tfParent = m_TypeParent[_layer]; UIBase ui = OpenUIInChild(_tfParent, _params); SetScalePr(ui); return ui; } public UIBase OpenUIInChild(string _uiName, eUINodeType _layer = eUINodeType.NodeUI, Type _typeOfT = null, params object[] _params) { Transform _tfParent = m_TypeParent[_layer]; return OpenUIInChild(_uiName, _tfParent, _typeOfT, _params); } public UIBase OpenUIInChild(Transform _tfParent = null, params object[] _params) where T : UIBase { Type vT = typeof(T); string uiName = vT.Name; if (_unAudioList.Contains(uiName)) return OpenUIInChild(uiName, _tfParent, vT, _params) as T; //播放打开UI音效 //HotfixEntry.Audio.PlayAudioOnce(Mode.Mode8); return OpenUIInChild(uiName, _tfParent, vT, _params) as T; } private UIBase OpenUIInChild(string _uiName, Transform _tfParent = null, Type _typeOfT = null, params object[] _params) { string uiName = _uiName; if (!AllUIPath.TryGetValue(uiName, out var uiPath)) { Debug.LogError("OpenUIInChild. not found UIPath. uiName:" + uiName); return null; } if (string.IsNullOrEmpty(uiPath)) { Debug.LogError("OpenUIInChild. string.IsNullOrEmpty(uiPath). uiName:" + uiName); return null; } if (_tfParent == null) _tfParent = m_TypeParent[eUINodeType.NodeUI]; // 如果已经有缓存的了 则直接激活换成缓存里的 if (UIDic.ContainsKey(uiName)) { var uiScript = UIDic[uiName]; if (uiScript == null || uiScript.gameObject == null) { UIDic.Remove(uiName); } else { uiScript.gameObject.SetActive(true); uiScript.transform.SetParent(_tfParent); if (_tfParent == m_TypeParent[eUINodeType.NodeUI]) UIMoveTop(uiScript); uiScript.Show(_params); SetScalePr(uiScript); return uiScript; } } InstantiateRequest _req; GameObject uiObj = Clone(out _req, uiPath, _tfParent); if (uiObj == null) { Debug.LogError("uiObj == null. uiPath:" + uiPath); return null; } uiObj.name = uiName; UIBase uiBase = uiObj.GetComponent(); if (uiBase == null) { uiBase = uiObj.AddComponent(_typeOfT) as UIBase; } UIDic.Add(uiName, uiBase); //添加对不需要按钮的统一处理 //UIUnActive.BatchInit(uiObj); //HotfixEntry.Resources.AddCache3(uiBase, _req); UIMoveTop(uiBase); uiBase.Show(_params); SetScalePr(uiBase); //if (HotfixEntry.IsPC) //{ // if (uiBase is ICrossPlatformCombineTarget combinable) // { // PCBorderUnit.Combine(combinable); // } //} return uiBase; } // 目前仅用于管理器, 比如UIMgr, 因为管理器本身基本是不释放的. 所以不能缓存到管理器中 public GameObject Clone(out InstantiateRequest _req, string _path, Transform t) { _req = Asset.InstantiateAsync(_path, t); _req?.WaitForCompletion(); return _req?.gameObject; } public void OpenUI(string uiName) { // 如果已经有缓存的了 则直接激活换成缓存里的 if (UIDic.ContainsKey(uiName)) { var uiScript = UIDic[uiName]; uiScript.gameObject.SetActive(true); UIMoveTop(uiScript); } } private void UIMoveTop(UIBase uiScript) { mTopUI = uiScript; MoveRootUp(uiScript.transform, m_NodeUIChildTop); MoveRootUp(m_NodeUIChildTop, uiScript.transform); } #endregion #region CloseUI /// /// 关闭UI 建议在UI内直接调用CloseUI(this) /// public void CloseUI(string _uiName) { var strNameAry = _uiName.Split('.'); _uiName = strNameAry[strNameAry.Length - 1]; if (!UIDic.TryGetValue(_uiName, out var ui)) { Debug.LogWarning("缓存中 没找到该UI _uiName:" + _uiName); return; } //这里改一下,直接删除ab包 if (!AllUIPath.TryGetValue(_uiName, out var uiPath)) { Debug.LogWarning("CloseUI. not found UIPath. uiName:" + _uiName); return; } Destroy(ui.gameObject); UIDic.Remove(_uiName); //Common.SetLoginGoQQbgMask(false); } /// /// 关闭UI /// public void CloseUI() where T : UIBase { string uiName = typeof(T).Name; CloseUI(uiName); } /// /// 关闭UI 建议在UI内直接调用CloseUI(this) /// /// 界面实力 public void CloseUI(UIBase _ui) { if (_ui == null) { Debug.LogError("CloseUI, _ui == null."); return; } Type _t = _ui.GetType(); string uiName = _t.Name; CloseUI(uiName); } public void CloseAllUI() { mTopUI = null; List tCloseList = new List(); foreach (var ui in UIDic.Values) { tCloseList.Add(ui); } foreach (var ui in tCloseList) { CloseUI(ui); } UIDic.Clear(); HideBg(); } #endregion #region HideUI public void Hide(UIBase _ui) { if (_ui == null) { Debug.LogError("CloseUI, _ui == null."); return; } Type _t = _ui.GetType(); string uiName = _t.Name; Hide(uiName); } public void Hide() where T : UIBase { string uiName = typeof(T).Name; Hide(uiName); } public void Hide(string uiName) { if (!UIDic.ContainsKey(uiName)) { Debug.LogError("缓存中 没找到该UI uiName:" + uiName); return; } var ui = UIDic[uiName]; if (ui == null) { UIDic.Remove(uiName); return; } //播放关闭声音 //if (!_unAudioList.Contains(uiName)) //{ // HotfixEntry.Audio.PlayAudioOnce(Mode.Mode9); //} ui.gameObject.SetActive(false); if (ui == mTopUI) mTopUI = null; } public void HideAll() { foreach (KeyValuePair Pair in UIDic) { Hide(Pair.Key); } } #endregion /// /// 判断某个界面是否已经打开 /// public bool IsOpen() where T : UIBase { string uiName = typeof(T).Name; return IsOpen(uiName); } public bool IsOpen(string uiName) { if (!UIDic.ContainsKey(uiName)) { //Debug.Log("缓存中 没找到该UI uiName:" + uiName); return false; } var ui = UIDic[uiName]; if (ui == null) { Debug.LogError("被非UIMgr销毁了的ui:" + uiName); UIDic.Remove(uiName); return false; } return ui.gameObject.activeSelf; } /// /// 获取打开的某个界面 /// /// /// null:没有打开 public T GetUI() where T : UIBase { string uiName = typeof(T).Name; return GetUI(uiName) as T; } /// /// 获取UI /// /// /// public UIBase GetUI(string _uiName) { if (UIDic.TryGetValue(_uiName, out var ui)) // .ContainsKey(_uiName)) { return ui; //return UIDic[_uiName]; } Debug.Log("GetUI. return null. _uiName:" + _uiName); return null; } /// /// 获取最顶层的UI /// /// null:没有打开的UI public UIBase GetTopUI() { if (mTopUI != null) return mTopUI; int maxSiblingIdx = -9999; foreach (var ui in UIDic.Values) { if (ui == null) continue; int siblingIdx = ui.transform.GetSiblingIndex(); if (siblingIdx <= maxSiblingIdx) continue; mTopUI = ui; maxSiblingIdx = siblingIdx; } if (mTopUI == null) { // 获取最外层 Debug.Log("GetTopUI. mTopUI == null. 当前没有打开的UI"); } return mTopUI; } public void HideBg() { if (m_imgBg.gameObject.activeSelf) m_imgBg.gameObject.SetActive(false); } public void Clean() { foreach (KeyValuePair Pair in UIDic) { if (Pair.Value.gameObject != null) GameObject.Destroy(Pair.Value.gameObject); } UIDic.Clear(); HideBg(); } // 清理除Loading以外的UI public void CleanExceptLoading() { List exceptUIList = new List() { "LoadingUI" }; CleanExceptList(exceptUIList); } // 清理除传入列表相关UI public void CleanExceptList(List _uiNameList = null) { mTopUI = null; if (_uiNameList == null || _uiNameList.Count <= 0) { Clean(); return; } List needRemoveKeyLst = new List(); foreach (KeyValuePair Pair in UIDic) { if (Pair.Value.transform.parent == m_NodeLoading) continue; if (Pair.Value.gameObject != null) { if (_uiNameList.Contains(Pair.Key)) continue; needRemoveKeyLst.Add(Pair.Key); } } for (int i = 0; i < needRemoveKeyLst.Count; i++) { CloseUI(needRemoveKeyLst[i]); UIDic.Remove(needRemoveKeyLst[i]); } needRemoveKeyLst.Clear(); HideBg(); } public void HideNodeAllUIButNpcTalkUI() { List tList = new List(); for (int i = 0; i < m_NodeUI.transform.childCount; i++) { string Name = m_NodeUI.transform.GetChild(i).name; if (Name.Contains("UI") && ( Name == "NpcTalkUI" || Name == "QuickEquipUI" || Name == "LvUpRechargeUI" || Name == "AttrPointTipsUI" )) { } else { if (Name != "Top") { tList.Add(Name); //Log.Debug(Name); } } } if (tList.Count > 0) { for (int i = 0; i < tList.Count; i++) { Hide(tList[i]); } } } public void HideNodeUIByForceTask() { for (int i = 0; i < m_NodeUI.transform.childCount; i++) { string Name = m_NodeUI.transform.GetChild(i).name; if (Name == "Top") continue; Hide(Name); } } public void CloseCamera() { m_camera.gameObject.SetActive(false); } public void ShowCamera() { if (m_camera) m_camera.gameObject.SetActive(true); } /// /// 把一个UI的Transform _Tf1 移到 另一个UI的Transform _Tf2 上面 /// public void MoveRootUp(Transform _Tf1, Transform _Tf2) { if (_Tf1 == null) return; if (_Tf2 == null) return; _Tf1.SetSiblingIndex(_Tf2.GetSiblingIndex() + 1); } /// /// 改变UI透明度, 先不对外开放功能 /// /// /// private void ChangeAlpha(Transform _tf, float _alpha) { // 是否有必要改成canvasGroup Image[] imageAry = _tf.GetComponentsInChildren(); for (int i = 0; i < imageAry.Length; i++) { Color old = imageAry[i].color; imageAry[i].color = new Color(old.r, old.g, old.b, _alpha); } Text[] textAry = _tf.GetComponentsInChildren(); for (int i = 0; i < textAry.Length; i++) { Color old = textAry[i].color; textAry[i].color = new Color(old.r, old.g, old.b, _alpha); } } #region bool bInitmScaleUIHashList = false; Dictionary mScaleUIHashList = new Dictionary(); public bool CheckIsScaleUI(UIBase ui) { if (!bInitmScaleUIHashList) { //mScaleUIHashList[typeof(ChoiceFruitUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(FruitInfoUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ClanUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(FullMapUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(DungeonUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PropExchangeUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(RoleMainHubUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(StoreMainHubUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SettingUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(XinRenAssistantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(OnlineRewardUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PetUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PC_PotentialFruitUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(TaskMainUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(RankListUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(TeamUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SocialUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ClanEmptyUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SkillMainUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(LoginSubcontractLoadUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(StallUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(MapTransportUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(FirstRechargeUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PotentialFruitUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(EquipRepairUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(EquipIdentificationUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SoulSynthesisUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(EquipRelevantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SplitRelevantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(GemstoneRelevantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PropSynthesisUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(TaskOfferRewardUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ItemRewardChoseUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(HelpUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SoulInlayUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(LifeSkillMainUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ActivityBooksUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ChallengeBossUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(StandingUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(InputTextUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ItemRewardChoseUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(LoginFangChenMiUI).GetHashCode()] = 0; ////mScaleUIHashList[typeof(LoginPrivacyUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(PetGradeUpUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ShopBuyUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(TeamInputLvUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SetNumChangeUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SetNumChangeNoItemUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(GameAssistantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(QRRewardUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ClanActivityUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ExpPoolUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(QQGamePrivilegesUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(QQGameDaWanKaUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(ZhanDouJiLuUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(LongZhouResultUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(GrandmasterRingStrenthUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(DebrisSynthesisUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(SuitEquipRelevantUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(CurrencyExchangeUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(FuncUnlockUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(XinRenAutoGameUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(FuncNewOpenUI).GetHashCode()] = 0; //mScaleUIHashList[typeof(WaiGuanUI).GetHashCode()] = 0; ////手机缩放 //mScaleUIHashList[typeof(RoleMainHubUI).GetHashCode()] = 1; //mScaleUIHashList[typeof(ShopMallUI).GetHashCode()] = 1; //mScaleUIHashList[typeof(ActivityUI).GetHashCode()] = 1; bInitmScaleUIHashList = true; } return mScaleUIHashList.ContainsKey(ui.GetType().GetHashCode()); } #endregion #region 获取点击UI的本体 //往上找,直到找到父物体为"Normal"(只调整Normal下界面顺序) List tParentTransList = new List(); Transform tResultTrans = null; List list = new List(); /// /// 点中ui /// public Transform ClickUI() { //场景中的EventSystem PointerEventData eventData = new PointerEventData(EventSystem.current); //鼠标位置 eventData.position = Input.mousePosition; //调用所有GraphicsRacaster里面的Raycast,然后内部会进行排序, //直接拿出来,取第一个就可以用了 EventSystem.current.RaycastAll(eventData, list); //这个函数抄的unity源码的,就是取第一个值 var raycast = FindFirstRaycast(list); //获取父类中事件注册接口 //如Button,Toggle之类的,毕竟我们想知道哪个Button被点击了,而不是哪张Image被点击了 //当然可以细分为IPointerClickHandler, IBeginDragHandler之类细节一点的,各位可以自己取尝试 var go = ExecuteEvents.GetEventHandler(raycast.gameObject); //既然没拿到button之类的,说明只有Image挡住了,取点中结果即可 if (go == null) { go = raycast.gameObject; } tParentTransList.Clear(); tResultTrans = null; return GetUIFormTrans(go.transform); } public Transform GetUIFormTrans(Transform tObj) { tParentTransList.Add(tObj); Transform tPar = tObj.transform.parent; if (tPar == null)//找到头了 return null; if (tPar.name == "NodeUI") { tParentTransList.Add(tPar); tResultTrans = tParentTransList[tParentTransList.Count - 2]; } else { GetUIFormTrans(tPar); } return tResultTrans; } /// /// Return the first valid RaycastResult. /// private RaycastResult FindFirstRaycast(List candidates) { for (var i = 0; i < candidates.Count; ++i) { if (candidates[i].gameObject == null) continue; return candidates[i]; } return new RaycastResult(); } #endregion #region SlotUnitPool //public Queue slotUnitPool = new Queue(); //public SlotUnit GetSlotUnit(Transform parent = null) //{ // if (slotUnitPool.Count > 0) // { // var slot = slotUnitPool.Dequeue(); // slot.transform.SetParent(parent, false); // slot.ClearBaseItem(); // slot.gameObject.SetActive(true); // return slot; // } // return CreateSlotUnitInstance(parent); //} //public SlotUnit CreateSlotUnitInstance(Transform parent = null) //{ // var slotGo = HotfixEntry.Resources.Clone(this, "Assets/GameAssets/Prefabs/UI/Backpack/SlotUnit.prefab"); // if (slotGo == null) // return null; // var slot = slotGo.AddComponent(); // slot.transform.SetParent(parent, false); // return slot; //} //public void ReleaseSlotUnit(SlotUnit slot) //{ // slot.transform.SetParent(AppEntry.OjbectPool.transform, false); // slot.gameObject.SetActive(false); // slotUnitPool.Enqueue(slot); //} //public void DestroyAllSlotUnit() //{ // while (slotUnitPool.Count > 0) // { // var slot = slotUnitPool.Dequeue(); // GameObject.DestroyImmediate(slot); // } //} #endregion }