关于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为单位,考虑界面分层。
5、然后才是写代码MCV,M是数据模型,V是界面,C是逻辑控制器
其中子控件要主动上报:
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! ");//文本改变
}
}
这样UI里面可以这样排列,你会发现里面的image没有挂载UIBehaviour组件,
而Button_N则多出这个组件,点击之后会是如下图
其中的Text_N的显示内容如下
最后一定要记住对于这些代码一定要分好层级
最好是每层代码都分成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下的我们要使用的组件的名字可以一样