对于u3d客户端最好的学习方法就是实践!!
今天终于有时间可以写写博客,这次我写一个基于ugui的ui模块,也可以理解为封装,把ui相关封装起来方便使用。
回到正题!
首先我会用到单例模式,不懂的自行百度。我这里添加一个创建gameobject的单例。
using UnityEngine;
using System.Collections;
public class MonoSingleton : MonoBehaviour where T : MonoSingleton
{
protected static readonly T instance = Create();
public static T GetSingleton()
{
return instance;
}
private static T Create()
{
T instance = GameObject.FindObjectOfType();
if (null == instance)
{
instance = new GameObject(typeof(T).Name + "_Singleton").AddComponent();
}
GameObject.DontDestroyOnLoad(instance);
return instance;
}
protected static V AddComponent() where V : MonoBehaviour
{
return instance.gameObject.AddComponent();
}
}
1.ui我采用的是ngui那种双摄像机,首先创建一个ui摄像机的单例吧
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class UICamera : MonoSingleton
{
public Camera UI_Camera { get; set; }
void Awake()
{
UI_Camera = GetComponent();
UI_Camera.clearFlags = CameraClearFlags.Depth;
UI_Camera.cullingMask = 1 << LayerMask.NameToLayer("UI");
UI_Camera.orthographic = true;
UI_Camera.orthographicSize = 3.2f;
}
}
2.基本东西已经准备好了,现在开始书写我们的ui框架
ui基本框架有三个东西
UISystem :管理ui,包括创建ui,查找ui,删除ui等等(其他功能可以自己扩展)
UIWidget:处理ui逻辑,注册ui事件(点击,拖拽之类),设置sprite、设置label等等接口(很多功能可以自己扩展,例如:点击音效,ui动画)
IEventListener : 是对EventTrigger进行下一层封装,封装成类似ngui事件监听
看UISystem的代码之前,我要补充一下,RectTransformUtility.CalculateRelativeRectTransformBounds可以计算ui的包围盒,不过他的大小位置是根据屏幕缩放之前的rect。 Canvas获取RectTransform. rect是屏幕缩放过的rect,因为我是按照高度适应,所以根据高度来算出比例来算出屏幕缩放之前rect,根据包围盒和Canvas的rect可以用来判断ui是否超出界面,判断超出有什么用?例如:物品属性面板是跟着物品图标位置改变而改变,如果靠太边,属性面板就会超出屏幕。如果超出会做相应工作把他放在屏幕内,这个代码已经写好,下次放出。
计算缩放前的rect代码如下
UISystem代码
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Canvas))]
[RequireComponent(typeof(CanvasScaler))]
[RequireComponent(typeof(GraphicRaycaster))]
[RequireComponent(typeof(EventSystem))]
[RequireComponent(typeof(StandaloneInputModule))]
[RequireComponent(typeof(TouchInputModule))]
public sealed class UISystem : MonoSingleton
{
public const int WIDTH = 960;
public const int HEIGHT = 640;
public Canvas Canvas { get; set; }
public CanvasScaler CanvasScaler { get; set; }
public Camera UI_Camera { get; set; }
public RectTransform UIRectTranform { get; set; }
public Rect UI_Rect { get; set; }
///
/// 存放由uisystem创建的ui
///
private Dictionary<string, UIWidget> m_UI_Dic = new Dictionary<string, UIWidget>();
void Awake()
{
this.gameObject.layer = LayerMask.NameToLayer("UI");
this.Canvas = GetComponent
UIWidget代码,注册事件我添加了一个根据ui名字注册和gameobject注册,其实都是gameobject注册 ,里面只添加了点击事件,其他事件可以自己添加。部分接口隐藏ui,显示ui,设置精灵,设置文字等等接口
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class UIWidget : MonoBehaviour
{
protected Dictionary<string, GameObject> m_Widgets = new Dictionary<string, GameObject>();
public const string CONTAIN_WORLD = "UI";
///
/// 初始化控件
///
///
protected void InstallWidgets(string[] aryName)
{
List trans = new List(gameObject.GetComponentsInChildren());
for (int i = 0; i < aryName.Length; i++)
{
for (int j = 0; j < trans.Count; j++)
{
if (trans[j].name == aryName[i])
{
m_Widgets[aryName[i]] = trans[j].gameObject;
trans.RemoveAt(j);
break;
}
}
}
}
///
/// 当前面板的rect
///
public RectTransform rectTransform
{
get
{
if(null == m_RectTransform)
{
m_RectTransform = GetComponent();
}
return m_RectTransform;
}
}
private RectTransform m_RectTransform;
///
/// 查找ui控件接口
///
///
///
public GameObject Find(string name)
{
if (!m_Widgets.ContainsKey(name)) { return null; }
return m_Widgets[name];
}
///
/// 通过gameobject注册点击事件
///
///
///
public void RegisterClickEvent(GameObject go, UIEventListener.VoidDelegate execute)
{
if (null == go) { return; }
UIEventListener.Get(go).onPointerClick = execute;
}
///
/// 通过控件名称注册点击事件
///
///
///
public void RegisterClickEvent(string widget, UIEventListener.VoidDelegate execute)
{
RegisterClickEvent(Find(widget), execute);
}
///
/// 设置精灵
///
///
///
public void SetSprite(GameObject go,Sprite sprite)
{
if (null == go) { return; }
Image image = go.GetComponent();
if (null == image) { return; }
image.sprite = sprite;
}
public void SetSprite(string widget, Sprite sprite)
{
SetSprite(Find(widget), sprite);
}
///
/// 设置进度条
///
///
///
public void SetSlider(GameObject go,float value)
{
if (null == go) { return; }
Slider slider = go.GetComponent();
if (null == slider) { return; }
slider.value = value;
}
public void SetSlider(string widget, float value)
{
SetSlider(Find(widget), value);
}
///
/// 设置toggle
///
///
///
public void SetToggle(GameObject go,bool enable)
{
if (null == go) { return; }
Toggle toggle = go.GetComponent();
if (null == toggle) { return; }
toggle.isOn = enable;
}
public void SetToggle(string widget,bool enable)
{
SetToggle(Find(widget), enable);
}
///
/// 设置文字
///
///
///
public void SetText(GameObject go,string content)
{
if (null == go) { return; }
Text text = go.GetComponent();
if (null == text) { return; }
text.text = content;
}
public void SetText(string widget,string content)
{
SetText(Find(widget), content);
}
///
/// 设置输入文字
///
///
///
public void SetInputText(GameObject go,string content)
{
if (null == go) { return; }
InputField input = go.GetComponent();
if (null == input) { return; }
input.text = content;
}
public void SetInputText(string widget,string content)
{
SetInputText(Find(widget), content);
}
///
/// 设置控件颜色
///
///
///
public void SetColor(GameObject go,Color color)
{
if (null == go) { return; }
Graphic graphic = go.GetComponent();
if (null == graphic) { return; }
graphic.color = color;
}
public void SetColor(string widget,Color color)
{
SetColor(Find(widget), color);
}
///
/// 获取进度条的value
///
///
///
public float GetSliderValue(GameObject go)
{
if (null == go) { return 0; }
Slider slider = go.GetComponent();
if (null == slider) { return 0; }
return slider.value;
}
public float GetSliderValue(string widget)
{
return GetSliderValue(Find(widget));
}
///
/// 获取toggle状态
///
///
///
public bool GetToggle(GameObject go)
{
if (null == go) { return false; }
Toggle toggle = go.GetComponent();
if (null == toggle) { return false; }
return toggle.isOn;
}
public void GetToggle(string widget)
{
GetToggle(Find(widget));
}
///
/// 获取输入框的文字
///
///
///
public string GetInputText(GameObject go)
{
if (null == go) { return string.Empty; }
InputField input = go.GetComponent();
if (null == input) { return string.Empty; }
return input.text;
}
public string GetInputText(string widget)
{
return GetInputText(Find(widget));
}
///
/// 显示控件
///
///
protected void Show(string name)
{
GameObject go = Find(name);
if (null == go) { return; }
go.SetActive(true);
}
///
/// 隐藏控件
///
///
protected void Hide(string name)
{
GameObject go = Find(name);
if (null == go) { return; }
go.SetActive(false);
}
public void SetVisable(bool visable)
{
gameObject.SetActive(visable);
}
}
UIEventListener 代码
这个不多说看过用过ngui的都知道。我只是继承EventTrigger,然后重写方法而已
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class UIEventListener : EventTrigger
{
public delegate void VoidDelegate(GameObject go, BaseEventData eventData);
public VoidDelegate onBeginDrag;
public VoidDelegate onCancel;
public VoidDelegate onDeSelect;
public VoidDelegate onDrag;
public VoidDelegate onDrop;
public VoidDelegate onEndDrag;
public VoidDelegate onInitializePotentialDrag;
public VoidDelegate onMove;
public VoidDelegate onPointerClick;
public VoidDelegate onPointerDown;
public VoidDelegate onPointerEnter;
public VoidDelegate onPointerExit;
public VoidDelegate onPointerUp;
public VoidDelegate onScroll;
public VoidDelegate onSelect;
public VoidDelegate onSubmit;
public VoidDelegate onUpdateSelect;
public override void OnBeginDrag(PointerEventData eventData)
{
if(null != onBeginDrag) { onBeginDrag(gameObject, eventData); }
}
public override void OnCancel(BaseEventData eventData)
{
if (null != onCancel) { onCancel(gameObject, eventData); }
}
public override void OnDeselect(BaseEventData eventData)
{
if (null != onDeSelect) { onDeSelect(gameObject, eventData); }
}
public override void OnDrag(PointerEventData eventData)
{
if (null != onDrag) { onDrag(gameObject, eventData); }
}
public override void OnDrop(PointerEventData eventData)
{
if (null != onDrop) { onDrop(gameObject, eventData); }
}
public override void OnEndDrag(PointerEventData eventData)
{
if (null != onEndDrag) { onEndDrag(gameObject, eventData); }
}
public override void OnInitializePotentialDrag(PointerEventData eventData)
{
if (null != onInitializePotentialDrag) { onInitializePotentialDrag(gameObject, eventData); }
}
public override void OnMove(AxisEventData eventData)
{
if (null != onMove) { onMove(gameObject, eventData); }
}
public override void OnPointerClick(PointerEventData eventData)
{
if (null != onPointerClick) { onPointerClick(gameObject, eventData); }
}
public override void OnPointerDown(PointerEventData eventData)
{
if (null != onPointerDown) { onPointerDown(gameObject, eventData); }
}
public override void OnPointerEnter(PointerEventData eventData)
{
if (null != onPointerEnter) { onPointerEnter(gameObject, eventData); }
}
public override void OnPointerExit(PointerEventData eventData)
{
if (null != onPointerExit) { onPointerExit(gameObject, eventData); }
}
public override void OnPointerUp(PointerEventData eventData)
{
if (null != onPointerUp) { onPointerUp(gameObject, eventData); }
}
public override void OnScroll(PointerEventData eventData)
{
if (null != onScroll) { onScroll(gameObject, eventData); }
}
public override void OnSelect(BaseEventData eventData)
{
if (null != onSelect) { onSelect(gameObject, eventData); }
}
public override void OnSubmit(BaseEventData eventData)
{
if (null != onSubmit) { onSubmit(gameObject, eventData); }
}
public override void OnUpdateSelected(BaseEventData eventData)
{
if (null != onUpdateSelect) { onUpdateSelect(gameObject, eventData); }
}
static public UIEventListener Get(GameObject go)
{
UIEventListener listener = go.GetComponent();
if (listener == null) listener = go.AddComponent();
return listener;
}
}
现在测试一下这个ui模块
首先添加一个ui预设先
然后预设路径放在
ui对应的脚本UITest
添加测试代码
运行效果,点击按钮就有打印
下期会放出ui超出屏幕的处理以及把ui位置设定在某个ui的8个方向的位置的计算