关于UI模块的封装

UI流程

1、先会由美术给一个效果图

2、然后美术将效果图切成碎图

3、程序拿到碎图后打成大图,基本都是使用TexturePacker来进行操作,一般都是用的png格式,然后选择的是RGBA4通道,RGB是红绿蓝通道,A则是透明通道,JPG则没有透明通道。(RGBA8888:每个通道占8bit ,8bit=1byte,1024byte=1k,1024k=1M,1024M=1T,1024T=1Pb。)其中设置图片大小:兼容所有机器一般只需要10241024,一般的中高端机则需要20482048

4、接下来就是拼UI了,拼UI的第一步就是先要把做一个panel,然后把UI的原图拖上去,将透明度调低,以此来进行无缝的拼接,注意一定要将层级分好。总结下来就是以Panel为单位,考虑界面分层。

unity安装新的模块 为unity添加模块_游戏开发

5、然后才是写代码MCV,M是数据模型,V是界面,C是逻辑控制器

unity安装新的模块 为unity添加模块_unity_02

其中子控件要主动上报:
1、我们就给任何一个子控件都挂上一下UIBehaviour,
2、使UIBehaviour注册到UIManager上

那么UIManager又应该怎么保存注册的子控件呢!
以上图为例,我们以panel为单位,panel下面又管理了很多的子控件

废话不多说,下面上代码

public class UIManager : MonoBehaviour
{
    public static UIManager Instance;//单例模式
    Dictionary<string, Dictionary<string, GameObject>> allWedgate;//字典类型,如上图那样的树形结构
    private void Awake()
    {
        Instance = this;//赋值
        allWedgate = new Dictionary<string, Dictionary<string, GameObject>>();//实例化
    }
    public void RegistGameObject(string panleName,string wedgateName,GameObject obj)//注册
    {
      
        if(!allWedgate .ContainsKey(panleName))//so the dictionary had not panle object that create one;
        {
            allWedgate[panleName] = new Dictionary<string, GameObject> ();
        }
        allWedgate[panleName].Add(wedgateName ,obj);
    }
    public GameObject GetGameObject(string panleName,string wedgateName)//获取物体
    {
        if(allWedgate [panleName]!=null)
        {
            return allWedgate[panleName][wedgateName];
        }
        return null;
    }
  
}

using UnityEngine.UI;
using UnityEngine.Events;
/// <summary>
/// 挂载到panle上的
/// </summary>
public class UIBase : MonoBehaviour
{
    
    private void Awake()
    {
        Transform[] allChildren = transform.GetComponentsInChildren <Transform> ();//获取孩子们的Transfrom
        for (int i = 0; i < allChildren.Length; i++)
        {
           if( allChildren[i].name.EndsWith ("_N"))//结尾为_N就是我们要用到的组件
            {
                allChildren[i].gameObject.AddComponent<UIBehaviour >();//添加UIBehaviour组件
            }
        }
    }
    public GameObject GetGameObject(string wedgateName)//获取对应的ui物体
    {
         
       GameObject tmpGameObject=  UIManager.Instance.GetGameObject(transform .name ,wedgateName);
        if(tmpGameObject !=null)
        {
            return tmpGameObject;
        }
        return null;
    }

    public UIBehaviour GetUIBehaviour(string wedgateName)//获取对应的UIBehaviour
    {
        UIBehaviour  tmpUIBehaviour= GetGameObject(wedgateName).GetComponent <UIBehaviour >();
        if(tmpUIBehaviour != null)
        {
            return tmpUIBehaviour; 
        }
        return null;
    }

    public void AddButtonListen(string wedgateName,UnityAction action)//Button监听事件
    {
        UIBehaviour tmpBehaviour = GetUIBehaviour(wedgateName);
        if(tmpBehaviour !=null)
        {
            tmpBehaviour.AddButtonListen(action);
        }
    }
    public void ChangeTextContent(string wedgateName,string content)//文本改变
    {

        UIBehaviour tmpBehaviour = GetUIBehaviour(wedgateName);
        if (tmpBehaviour != null)
        {
            tmpBehaviour.ChangeTextContent (content);
        }
    }
}


using UnityEngine.UI;
using UnityEngine.Events;

public class UIBehaviour : MonoBehaviour
{
    private void Awake()
    {
        UIBase uiBase = transform.GetComponentInParent<UIBase>();//找到上层的panle
        UIManager.Instance.RegistGameObject(uiBase .name ,transform .name ,gameObject );//在UIManager里面注册
    }


    public void AddButtonListen(UnityAction action)//Button监听事件
    {
        Button tmpButton = transform.GetComponent<Button>();
        if(tmpButton !=null)
        {
            tmpButton.onClick.AddListener(action);
        }
    }
    public void AddSliderListen(UnityAction<float> action)//Slider监听事件
    {
        Slider tmpSlider = transform.GetComponent<Slider>();
        if (tmpSlider != null)
        {
            tmpSlider.onValueChanged .AddListener(action);
        }
    }
    public void AddInputFieldEndEditorListen(UnityAction<string> action)//输入框编辑结束
    {
        InputField tmpInputField = transform.GetComponent<InputField>();
        if (tmpInputField != null)
        {
            tmpInputField.onEndEdit .AddListener(action);
        }
    }
    public void AddInputFieldonValueChangeListen(UnityAction<string> action)//输入框内容改变
    {
        InputField tmpInputField = transform.GetComponent<InputField>();
        if (tmpInputField != null)
        {
            tmpInputField.onValueChanged .AddListener(action);
        }
    }
    public void ChangeTextContent(string content)//文本内容改变
    {
        Text tmpText = transform.GetComponent<Text>();
        if (tmpText != null)
        {
            tmpText.text=content;
        }
    }
    public void ChangeImageSprite(Sprite name)//图片精灵更改
    {
        Image tmpImage = transform.GetComponent<Image>();
        if (tmpImage != null)
        {
            tmpImage.sprite = name;
        }
    }
}


public class UIUse : UIBase
{
    public void  OnClick()
    {
        Debug.Log("点击成功!");
    }
    // Start is called before the first frame update
    void Start()
    {
        AddButtonListen("Button_N",OnClick);//增加ButtonListener
        ChangeTextContent("Text_N","100,you are my heart! ");//文本改变
}
}

unity安装新的模块 为unity添加模块_UI模块_03


这样UI里面可以这样排列,你会发现里面的image没有挂载UIBehaviour组件,

而Button_N则多出这个组件,点击之后会是如下图

unity安装新的模块 为unity添加模块_UI模块_04


其中的Text_N的显示内容如下

unity安装新的模块 为unity添加模块_学习日记_05


最后一定要记住对于这些代码一定要分好层级
最好是每层代码都分成M层和C层

如同下面的注册代码一样

public class RegistModle//数据层
{
    public string password;
    public string userName;
}

public class RegistLogic//逻辑层
{
    public void OnClick()
    {
        Debug.Log("点击成功!");
    }
}

public class Regist :UIBase 
{

    RegistLogic registLogic = new RegistLogic();
    // Start is called before the first frame update
    void Start()
    {
        AddButtonListen("Button_N", registLogic.OnClick);//增加ButtonListener

    }
}

这样的话,在进行修改的时候,就可以只修改一层里面的,其他层的就不用修改了
不要害怕类写得多,要尽量的进行拆分,当你的每个类的代码不超过200行的时候
,你的架构思想也就成型了。

还有就是上面的这个UI模块需要注意以下几点
1、不同的panle的名字不能一样
2、同一个panle下我们要使用的组件的名字不能一样
3、不同的panle下的我们要使用的组件的名字可以一样