Unity手游框架 之 界面管理(一)

引子

界面管理是做什么用的?为了回答这个问题让我们先来罗列与界面操作相关的代码:

  • 在网络消息的回掉函数中我们发现了对界面的显示、隐藏及遮挡关系调整的操作。
public static void OnPacket_UserLogon(object pack)
{
    ... ...
    Debug.Log("Logon Succeed");
    Gamedata.me.userinfo = userLogon.UserInfo;
    PanelManager.me.HideAll(); // 界面的隐藏
    PanelManager.me.Get((int)PanelId.PanelMain).Show(); // 界面的显示
    PanelManager.me.Get((int)PanelId.PanelMain).ToTop(); // 调整界面到最前方    
    ... ...
}
  • 在界面的初始化函数中我们发现了获取界面控件的操作
public class PanelLogon : PanelBase
{
    InputField username; // 用户名
    InputField password; // 密码
    public override void Init()
    {
        ... ...
        username = controls.GetInputField("InputFieldUsername");
        password = controls.GetInputField("InputFieldPassword");
        ... ...        
    }
}
  • 在游戏初始化阶段,我们发现了为向PanelManager中注册Prfab的操作。
PanelManager.me.RegistPrefab((int)PanelId.PanelLogon, AssetManager.me.GetPanel("PanelLogon"));
PanelManager.me.RegistPrefab((int)PanelId.PanelMain, AssetManager.me.GetPanel("PanelMain"));
  • 在某界面中我们发现了事件处理函数。
void ProcessProgress(EventProgress evt)
{
    int intProgress = (int)(evt.progress * 100);
    txProcess.text = intProgress.ToString();
}

整理以上罗列出的代码,给出本文的界面管理的内容:

  • 界面的显示、隐藏、遮挡关系。
  • 界面的加载与卸载。
  • 界面控件的获得。
  • 界面中的事件响应。
  • 除以上在代码中罗列的内容外,本文还加入了部分界面管理与热跟新融合的部分内容。

本文的思路: 整理分析常见的界面管理的数据结构和遮挡关系管理方法,并给出本文采用的遮挡关系。整理分析常见的控件获得方式,给出本文采用的控件获取方式。讲解PanelBase和PanelManager中的主要函数来理解界面的显示、隐藏、加载及卸载的实现。界面中全局事件的相应会放到事件系统中讲解,最后附录中给出本文的完整的源代码。

界面管理的数据结构和遮挡关系的管理方法

界面管理的数据结构一般有两中:栈结构和对结构。
* 栈结构为基础的界面管理。
在这种方式中界面的显示相当与如栈,而界面的隐藏则相当于出栈。这种方式的好处是结构清晰、遮挡关系的管理简单并天生就有界面显示流的逆向追踪能力。当显示一个界面时,将这个界面放入栈顶并显示,处于栈顶的界面永远处于遮挡关系的最前方。当隐藏一个界面是将从这个界面到栈顶的界面一律出栈并隐藏。这种方式的不足是经常不能满足策划对界管理的要求,于是加入各种补丁使得原本清晰简单的结构变的复杂而混乱。
* 以堆结构为基础的界面管理。
这种方式在实现遮挡关系管理上要比栈结构复杂,要实现诸如ToTop、ToBottom、MoveForward、MoveBackward、SetQueueIndex等控制遮挡关系的函数。

本文实现的是阉割版的堆结构为基础的界面管理,即仅实现了众多遮挡控制函数中的ToTop,在使用上显示即ToTop。另外,有些复杂的界面管理还实现了界面显示流的逆向追踪,这个也不在本文的讨论范围。

界面中控件的取得

常见的控件获取的三种方式
* 拖拽式。 这种方式大概是这样实现的, 首先在代码中声明控件变量,在制作Panel的prefab时将相应的控件拖拽到prefab上。 代码中大概是这样的:

class PanelHero : Behaviour
{
    public Button btnUpLevel;
    public Button btnUpStar;
    public void Awake()
    {
        btnUpLevel.onClick.AddListener(OnUpLevelClick);
        btnUpStar.OnClick.AddListener(OnUpStarClick);
    }
    ... ...
}
  • 路径查找式。这中方式与第一中方式类似, 但在制作界面的Prefab时不需要将控件拖拽到相应的变量上,在加载界面是由程序通过路径查找的方式找到相应的空间, 代码大概是这样的。
class PanelHero : Behaviour
{
    public Button btnUpLevel;
    public Button btnUpStar;
    public void Awake()
    {
        btnUpLevel = transform.Find("HeroLevel/ButtonUpLevel").GetComponent<Button>();
        btnUpStar = trnaform.Find("HeroQualityAndStar/ButtonUpStar").GetComponent<Button>();
        btnUpLevel.onClick.AddListener(OnUpLevelClick);
        btnUpStar.OnClick.AddListener(OnUpStarClick);
    }
    ... ...
}
  • 注册式。 这种方式需要两个类, Register和Container, 在制作控件时将Container置于Panel上, 将Register置于要与程序产生关联的控件上, 在程序中使用使用首先得到Container,然后在Container中取得相应的控件。 代码如下
    // 控件注册器
    class UiControlRegistor : MonoBehaviour
    {
        // 指定的目标容器
        public UiControlContainer PointedContainer = null;
        public virtual void Awake()
        {
            container.RegistObject(name, gameObject); // 注册本控件
        }

        // 得到控件的目标容器
        public UiControlContainer container
        {
            // 如果制定了目标容器就返回制定的目标容器,
            // 否则依次向跟节点查找容器, 返回路径上的第一个容器作为目标容器
            get { return PointedContainer ? PointedContainer :
             transform.GetComponentInParent<UiControlContainer>(); }
        }
    }
    // 控件容器
    class UiControlContainer : MonoBehaviour
    {
        // GameObject 类型的容器
        Dictionary<string, GameObject> objects = new Dictionary<string, GameObject>();

        // 泛型的控件注册函数
        bool RegistT<T>(Dictionary<string, T> datas, string name, T unit)
        {
            if (datas.ContainsKey(name))
            {
                Debug.LogError("name(" + name + ") already exist");
                return false;
            }
            datas.Add(name, unit);
            return true;
        }

        // GameObject类型的控件注册函数
        public bool RegistObject(string name, GameObject obj)
        {
            return RegistT(objects, name, obj);
        }
        ... ...
    }

下面给出这三种方案的对比:
第一种方案(拖拽式)的优点, 简洁,直观,效率高。缺点prefab与对应的脚本关联行强,难于分离脚本开发与perfab制作,很难支持lua热更新。
第二种方案(路径查找式)的优点,简洁,直观, prefab的制作不再依赖与脚本开发。缺点查找的效率低,脚本开发依旧依赖与prefab制作。这种方案可以将prefab的制作人员与脚本开发人员分离,但每次修改prefab后脚本依旧要紧随其后的修改。这种方案可以支持Lua热跟新。
第三种方案(注册式)优点prefab的制作与脚本开发很好的分离,很好的支持lua热跟新。效率介于前两种方案之间,缺点是结构稍显复杂。本文采用的方案是第三种方案。

PanelBase的主要函数

PanelBase是界面的基类, 主要的接口有Init,Show, Hide, Refresh,与层次相关的接口前面已经提到过了,本文采用的是阉割版,因此在这个类中看不到遮挡关系系列的函数。对于界面控件的响应函数应该放到具体的Panel里,对于全局事件的相应放到事件系统中讲解。

/// <summary>
/// 界面的基类
/// 定义了诸如Init、Show、Hide、Refresh等可重写的流程函数
/// </summary>
[RequireComponent(typeof(UiControlContainer))]
public class PanelBase : MonoBehaviour
{        
    /// <summary>
    /// 控件容器
    /// </summary>
    public UiControlContainer controls { get { return GetComponent<UiControlContainer>();  } }

    /// <summary>
    /// 所有SubPanel
    /// </summary>
    public PanelBase[] subPanels { get { return controls.panelbases.Values.ToArray<PanelBase>(); } }

    /// <summary>
    /// 根据名字获取Button控件
    /// </summary>
    /// <param name="name">Button的名字</param>
    /// <returns>Button控件</returns>
    public virtual void Init()
    {
        foreach (PanelBase subPanel in subPanels)
        {
            bool active = gameObject.activeSelf;
            gameObject.SetActive(true);
            foreach (PanelBase subPanel in subPanels)
            {
                subPanel.Init();
            }
            gameObject.SetActive(active);
        }
    }

    /// <summary>
    /// 显示界面
    /// </summary>
    public virtual void Show()
    {
        gameObject.SetActive(true);
    }

    /// <summary>
    /// 隐藏界面
    /// </summary>
    public virtual void Hide()
    {
        gameObject.SetActive(false);
    }

/// <summary>
/// 刷新界面
/// </summary>
    public virtual void Refresh()
    {
    }
}

PanelManager的主要函数

PanelManager是界面管理的核心类, 主要函数有RegistPrefab、Get、HideAll、RefreshAll等

public class PanelManager : Singleton<PanelManager>
{
    // 界面的实例化函数
    public delegate PanelBase FuncInstanceUiBase(PanelBase prefab);
    public FuncInstanceUiBase InstanceUiBase;

    // prefab 容器
    private readonly Dictionary<int, PanelBase> prefabs = new Dictionary<int, PanelBase>();

    // 已经加载的界面容器
    private readonly Dictionary<int, PanelBase> uis = new Dictionary<int, PanelBase>();

    /// <summary>
    ///  注册界面的Prefab
    /// </summary>
    /// <param name="uiid">界面的类型id</param>
    /// <param name="prefab">界面的prefab</param>
    public void RegistPrefab(int uiid, PanelBase prefab)
    {   
        prefabs.Add(uiid, prefab);
    }

    /// <summary>
    /// 获取界面
    /// </summary>
    /// <param name="uiid">界面的类型id</param>
    /// <returns></returns>
    public PanelBase Get(int uiid)
    {
        if (uis.ContainsKey(uiid))
            return uis[uiid];

        if (prefabs.ContainsKey(uiid))
        {
            var ui = InstanceUiBase(prefabs[uiid]);
            uis.Add(uiid, ui);  
            ui.gameObject.SetActive(true);              
            ui.name = ui.name.Substring(0, ui.name.IndexOf("(Clone)"));                
            ToTop(ui);
            ui.Init();
            AdjustPanelPosition(ui);
        }

        return null;
    }

    /// <summary>
    /// 隐藏所有界面
    /// </summary>
    public void HideAll()
    {
        foreach (var ui in uis.Values)
            ui.Hide();
    }

    /// <summary>
    /// 显示所有界面
    /// </summary>
    public void RefreshAll()
    {
        foreach (var ui in uis.Values)
            ui.Refresh();
    }
}

小结

本文从常见的界面相关的源代码出发,提出了界面管理的基础功能,并重点讲解了界面控件的获得和界面管理的数据结构。有关界面管理的高级部分,例如界面的过度动画,界面切换触发的功能(例如新手引导),界面的导航与追踪等部分将在下一篇界面管理的文章中给出。

附:完整源代码

// PanelBase.cs
// Author: Iann

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using System.Reflection;

namespace Assets.Script.Frame
{
    /// <summary>
    /// 界面的基类
    /// 定义了诸如Init、Show、Hide、Refresh等可重写的流程函数
    /// </summary>
    [RequireComponent(typeof(UiControlContainer))]
    public class PanelBase : MonoBehaviour
    {
        /// <summary>
        /// 控件容器
        /// </summary>
        public UiControlContainer controls { get { return GetComponent<UiControlContainer>();  } }

        /// <summary>
        /// 所有SubPanel
        /// </summary>
        public PanelBase[] subPanels { get { return controls.panelbases.Values.ToArray<PanelBase>(); } }

        /// <summary>
        /// 根据名字获取Button控件
        /// </summary>
        /// <param name="name">Button的名字</param>
        /// <returns>Button控件</returns>
        public virtual Button GetButton(string name)
        {
            return controls.GetButton(name);
        }

        /// <summary>
        /// 根据名字获取Button控件
        /// </summary>
        /// <param name="name">Button的名字</param>
        /// <returns>Button控件</returns>
        public virtual Text GetText(string name)
        {
            return controls.GetText(name);
        }

        /// <summary>
        /// 根据名字获取Image控件
        /// </summary>
        /// <param name="name">Image的名字</param>
        /// <returns>Image控件</returns>
        public virtual Image GetImage(string name)
        {
            return controls.GetImage(name);
        }

        /// <summary>
        /// 根据名字获取SubPanel控件
        /// </summary>
        /// <param name="name">SubPanel的名字</param>
        /// <returns>SubPanel控件</returns>
        public virtual PanelBase GetSubPanel(string name)
        {
            return controls.GetPanelBase(name);
        }

        /// <summary>
        /// 界面的初始化函数
        /// 一般重载这个函数的主要目的是初始化界面控件
        /// 注意控件的注册是在Awake函数中进行的,保证在调用container.get的时候控件注册器的Awake已经调用
        /// </summary>
        public virtual void Init()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("Init Panel " + name + ".");
#endif

            bool active = gameObject.activeSelf;
            gameObject.SetActive(true);  // 确保初始化前UiControlRegister的Awake已经调用
            foreach (PanelBase subPanel in subPanels)
            {
                subPanel.Init();
            }
            gameObject.SetActive(active);
        }

        /// <summary>
        /// 显示界面
        /// </summary>
        public virtual void Show()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("PaneBase(" + name + ").Show");
#endif
            gameObject.SetActive(true);
            //OnShow();
            Refresh();
        }

        /// <summary>
        /// 隐藏界面
        /// </summary>
        public virtual void Hide()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("PaneBase(" + name + ").Hide");
#endif
            gameObject.SetActive(false);
        }

        /// <summary>
        /// 刷新界面
        /// </summary>
        public virtual void Refresh()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("PanelBase(" + name + ").Refresh");
#endif
        }

    }


}
// PanelManager.cs
// Author: Iann

using System.Collections.Generic;
using UnityEngine;

namespace Assets.Script.Frame
{
    /// <summary>
    /// 界面管理类
    /// 本类提供了界面的加载,显示,隐藏,(关闭)功能
    /// 动画过度暂未实现
    /// 导航功能暂未实现
    /// </summary>
    public class PanelManager : Singleton<PanelManager>
    {
        // 界面的实例化函数
        public delegate PanelBase FuncInstanceUiBase(PanelBase prefab);
        public FuncInstanceUiBase InstanceUiBase;

        // prefab 容器
        private readonly Dictionary<int, PanelBase> prefabs = new Dictionary<int, PanelBase>();

        // 已经加载的界面容器
        private readonly Dictionary<int, PanelBase> uis = new Dictionary<int, PanelBase>();


        public void Regist(int uiid, PanelBase ui)
        {
            //types.Add(typeof(T), uiid);
            uis.Add(uiid, ui);
        }

        /// <summary>
        ///  注册界面的Prefab
        /// </summary>
        /// <param name="uiid">界面的类型id</param>
        /// <param name="prefab">界面的prefab</param>
        public void RegistPrefab(int uiid, PanelBase prefab)
        {
            if (prefab == null)
            {
                Debug.LogError(string.Format("PanelManager.RegistPrefab({0},{1}) Failed !!!",
                     uiid, prefab));
                return;
            }

#if USE_LOG
            Debug.Log(string.Format("PanelManager.RegistPrefab({0},{1}", uiid, prefab));
#endif 

            prefabs.Add(uiid, prefab);
        }

        /// <summary>
        /// 获取界面
        /// </summary>
        /// <param name="uiid">界面的类型id</param>
        /// <returns></returns>
        public PanelBase Get(int uiid)
        {
            //如果界面已经加载过, 返回已经加载过的界面
            if (uis.ContainsKey(uiid))
                return uis[uiid];

            // 加载界面
            if (prefabs.ContainsKey(uiid))
            {
                if (prefabs[uiid] == null)
                {
                    Debug.LogError((PanelId)uiid);
                }
                var ui = InstanceUiBase(prefabs[uiid]);
                uis.Add(uiid, ui);
                ui.gameObject.SetActive(true); // 确保初始化前UiControlRegister的Awake已经调用
                ui.name = ui.name.Substring(0, ui.name.IndexOf("(Clone)"));                
                ToTop(ui);
                ui.Init();
                AdjustPanelPosition(ui);
                return ui;
            }

            return null;
        }

        /// <summary>
        /// 调整Panel的位置布局
        /// </summary>
        /// <param name="ui">待调整的Panel</param>
        void AdjustPanelPosition(PanelBase ui)
        {
            ui.GetComponent<RectTransform>().SetParent(GameObject.Find("Canvas").transform);
            var rt = ui.GetComponent<RectTransform>();
            var op = ui.GetComponent<RectTransformAdjustor>();
            if (op != null)
            {
                op.Adjust();
            }
            else
            {
                ui.transform.localPosition = Vector3.zero;
                ui.transform.localScale = Vector3.one;
            }
        }

        /// <summary>
        /// 将Panel放到最前面
        /// </summary>
        /// <param name="ui">待调整的Panel</param>
        void ToTop(PanelBase ui)
        {
            ui.transform.SetAsLastSibling();
        }

        /// <summary>
        /// 隐藏所有界面
        /// </summary>
        public void HideAll()
        {
            foreach (var ui in uis.Values)
                ui.Hide();
        }

        /// <summary>
        /// 显示所有界面
        /// </summary>
        public void RefreshAll()
        {
            foreach (var ui in uis.Values)
                ui.Refresh();
        }
    }
}
// UiControlContainer.cs
// Author: Iann


using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

namespace Assets.Script.Frame
{
    public class UiControlContainer : MonoBehaviour
    {
        private readonly Dictionary<string, Button> buttons = new Dictionary<string, Button>();
        private readonly Dictionary<string, Image> images = new Dictionary<string, Image>();
        private readonly Dictionary<string, InputField> inputs = new Dictionary<string, InputField>();
        private readonly Dictionary<string, Text> texts = new Dictionary<string, Text>();
        private readonly Dictionary<string, Slider> sliders = new Dictionary<string, Slider>();
        private readonly Dictionary<string, GameObject> objects = new Dictionary<string, GameObject>();
        public Dictionary<string, PanelBase> panelbases = new Dictionary<string, PanelBase>();

        private bool RegistT<T>(Dictionary<string, T> datas, string name, T unit)
        {
            if (datas.ContainsKey(name))
            {
                Debug.LogError("name(" + name + ") already exist");
                return false;
            }
            datas.Add(name, unit);
            return true;
        }

        private bool UnRegistT<T>(Dictionary<string, T> datas, string name)
        {
            if (!datas.ContainsKey(name))
            {
                Debug.LogError("name not exist");
                return false;
            }
            datas.Remove(name);
            return true;
        }

        // Object
        public bool RegistObject(string name, GameObject obj)
        {
            return RegistT(objects, name, obj);
        }

        public bool UnRegistObject(string name)
        {
            return UnRegistT(objects, name);
        }

        public GameObject GetObject(string name)
        {
            if (objects.ContainsKey(name))
                return objects[name];
            return null;
        }

        // Button
        public bool RegistButton(string name, Button button)
        {
            return RegistT(buttons, name, button);
        }

        public bool UnRegistButton(string name)
        {
            return UnRegistT(buttons, name);
        }

        public Button GetButton(string name)
        {
            if (buttons.ContainsKey(name))
                return buttons[name];
            return null;
        }


        // Text
        public bool RegistText(string name, Text text)
        {
            return RegistT(texts, name, text);
        }

        public bool UnRegistText(string name)
        {
            return UnRegistT(texts, name);
        }

        public Text GetText(string name)
        {
            if (texts.ContainsKey(name))
                return texts[name];
            return null;
        }

        // Slider
        public bool RegistSlider(string name, Slider slid)
        {
            return RegistT(sliders, name, slid);
        }

        public bool UnRegistSlider(string name)
        {
            return UnRegistT(sliders, name);
        }

        public Slider GetSlider(string name)
        {
            if (sliders.ContainsKey(name))
                return sliders[name];
            return null;
        }

        // Image 
        public bool RegistImage(string name, Image image)
        {
            return RegistT(images, name, image);
        }

        public bool UnRegistImage(string name)
        {
            return UnRegistT(images, name);
        }

        public Image GetImage(string name)
        {
            if (images.ContainsKey(name))
                return images[name];
            return null;
        }


        // ImputFiled 
        public bool RegistInputField(string name, InputField inputFiled)
        {
            return RegistT(inputs, name, inputFiled);
        }

        public bool UnRegistInputField(string name)
        {
            return UnRegistT(inputs, name);
        }

        public InputField GetInputField(string name)
        {
            if (inputs.ContainsKey(name))
                return inputs[name];
            return null;
        }

        // PanelBase
        public bool RegistPanelBase(string name, PanelBase panelBase)
        {
            return RegistT(panelbases, name, panelBase);
        }

        public bool UnRegistPanelBase(string name)
        {
            return UnRegistT(panelbases, name);
        }

        public PanelBase GetPanelBase(string name)
        {
            if (panelbases.ContainsKey(name))
                return panelbases[name];
            return null;
        }
    }

}
// UiControlRegistor.cs
// Author: Iann


using UnityEngine;


namespace Assets.Script.Frame
{

    /// <summary>
    /// 界面控件注册器的基类
    /// </summary>
    class UiControlRegistor : MonoBehaviour
    {
        /// <summary>
        /// 指定的界面控件容器
        /// </summary>
        public UiControlContainer PointedContainer = null;

        /// <summary>
        /// 注册后立即删除本注册器, 用于多次加载的选项
        /// </summary>
        public bool removeThisWhenAwake = false;

        /// <summary>
        /// 唤醒函数, 我们的注册就是在这个函数中实现的
        /// </summary>
        public virtual void Awake()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("UiBehaviour(" + name + ").Awake");
#endif
            container.RegistObject(name, gameObject);
            if (removeThisWhenAwake)
            {
                DestroyImmediate(this);
            }
        }

        /// <summary>
        /// 销毁函数, 反注册写在这个函数中
        /// </summary>
        public virtual void Destroy()
        {
#if USE_LOG && LOG_FRAME_UI
            Debug.Log("UiBehaviour(" + name + ").Destroy");
#endif
            if (!removeThisWhenAwake)
                container.UnRegistObject(name);
        }

        /// <summary>
        ///  如果制定了目标容器就返回制定的目标容器, 
        ///  否则依次向跟节点查找容器, 返回路径上的第一个容器作为目标容器
        /// </summary>
        public UiControlContainer container { get { return PointedContainer ? 
            PointedContainer : transform.GetComponentInParent<UiControlContainer>(); } }
    }
}
// UiControlContainer.cs
// Author: Iann


using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

namespace Assets.Script.Frame
{
    /// <summary>
    /// 控件容器
    /// </summary>
    public class UiControlContainer : MonoBehaviour
    {
        //各种类型的器皿
        private Dictionary<string, Button> buttons = new Dictionary<string, Button>();
        private Dictionary<string, Image> images = new Dictionary<string, Image>();
        private Dictionary<string, InputField> inputs = new Dictionary<string, InputField>();
        private Dictionary<string, Text> texts = new Dictionary<string, Text>();
        private Dictionary<string, Slider> sliders = new Dictionary<string, Slider>();
        private Dictionary<string, GameObject> objects = new Dictionary<string, GameObject>();
        private Dictionary<string, PanelBase> panelbases = new Dictionary<string, PanelBase>();

        /// <summary>
        /// 泛型的注册函数
        /// </summary>
        /// <typeparam name="T">注册的类型</typeparam>
        /// <param name="datas">注册用到的器皿</param>
        /// <param name="name">控件名称</param>
        /// <param name="unit">控件Instance</param>
        /// <returns></returns>
        private bool RegistT<T>(Dictionary<string, T> datas, string name, T unit)
        {
            if (datas.ContainsKey(name))
            {
                Debug.LogError("name(" + name + ") already exist");
                return false;
            }
            datas.Add(name, unit);
            return true;
        }

        /// <summary>
        /// 泛型的反注册函数
        /// </summary>
        /// <typeparam name="T">反注册的类型</typeparam>
        /// <param name="datas">反注册用到的器皿</param>
        /// <param name="name">控件名称</param>
        /// <returns></returns>
        private bool UnRegistT<T>(Dictionary<string, T> datas, string name)
        {
            if (!datas.ContainsKey(name))
            {
                Debug.LogError("name not exist");
                return false;
            }
            datas.Remove(name);
            return true;
        }

        /// <summary>
        /// 注册GameObject
        /// </summary>
        /// <param name="name">GameObject的名字</param>
        /// <param name="obj">实例</param>
        /// <returns></returns>
        public bool RegistObject(string name, GameObject obj)
        {
            return RegistT(objects, name, obj);
        }

        /// <summary>
        /// 反注册GameObject
        /// </summary>
        /// <param name="name">GameObject的名字</param>
        /// <returns></returns>
        public bool UnRegistObject(string name)
        {
            return UnRegistT(objects, name);
        }

        /// <summary>
        /// 获得GameObeject
        /// </summary>
        /// <param name="name">GameObject的名字</param>
        /// <returns></returns>
        public GameObject GetObject(string name)
        {
            if (objects.ContainsKey(name))
                return objects[name];
            return null;
        }

        // Button
        public bool RegistButton(string name, Button button)
        {
            return RegistT(buttons, name, button);
        }

        public bool UnRegistButton(string name)
        {
            return UnRegistT(buttons, name);
        }

        public Button GetButton(string name)
        {
            if (buttons.ContainsKey(name))
                return buttons[name];
            return null;
        }


        // Text
        public bool RegistText(string name, Text text)
        {
            return RegistT(texts, name, text);
        }

        public bool UnRegistText(string name)
        {
            return UnRegistT(texts, name);
        }

        public Text GetText(string name)
        {
            if (texts.ContainsKey(name))
                return texts[name];
            return null;
        }

        // Slider
        public bool RegistSlider(string name, Slider slid)
        {
            return RegistT(sliders, name, slid);
        }

        public bool UnRegistSlider(string name)
        {
            return UnRegistT(sliders, name);
        }

        public Slider GetSlider(string name)
        {
            if (sliders.ContainsKey(name))
                return sliders[name];
            return null;
        }

        // Image 
        public bool RegistImage(string name, Image image)
        {
            return RegistT(images, name, image);
        }

        public bool UnRegistImage(string name)
        {
            return UnRegistT(images, name);
        }

        public Image GetImage(string name)
        {
            if (images.ContainsKey(name))
                return images[name];
            return null;
        }


        // ImputFiled 
        public bool RegistInputField(string name, InputField inputFiled)
        {
            return RegistT(inputs, name, inputFiled);
        }

        public bool UnRegistInputField(string name)
        {
            return UnRegistT(inputs, name);
        }

        public InputField GetInputField(string name)
        {
            if (inputs.ContainsKey(name))
                return inputs[name];
            return null;
        }

        // PanelBase
        public bool RegistPanelBase(string name, PanelBase panelBase)
        {
            return RegistT(panelbases, name, panelBase);
        }

        public bool UnRegistPanelBase(string name)
        {
            return UnRegistT(panelbases, name);
        }

        public PanelBase GetPanelBase(string name)
        {
            if (panelbases.ContainsKey(name))
                return panelbases[name];
            return null;
        }
    }

}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值