最近换了公司(仍然是实习狗),坐标在上海, 楼上是Unity总部。很开心~~
上海和广东差别 并不是很大。就是天气比较冷,口味偏甜, 这家公司是创业公司,做教育类应用的, VR/AR MR 等, 第一天 就要上手SDK,也不是很难,Zspace的 相对VRTK来说 比较 简单,开发工程中遇到Button交互,所以要对它进行 重写,设备是 用射线进行 探测,
其实 重写Button也比较简单,也可以不用重写, 但还是建议重写会比较好。
之前有写过射线交互的例子
https://blog.csdn.net/qq2512667/article/details/79493117
https://blog.csdn.net/qq2512667/article/details/79842850
原理都差不多的, 射线交互 现在用的挺多的,
NGUI 用的就是射线探测
但UGUI不是,是根据坐标,射线,结合去判断的·。
Button 继承自 Selectable
官方源码
FormerlySerializedAs( "“onClick”) ButtonClickEvent m_Onclick
这个特性就是备胎特性,当Onclick被删除 后, Onlickx序列化后就存在 m_Onclick 中
DoStateTransition(currentSelectionState, false);
这个 方法 比较重要,就是设置Button的交互转换状态,在重写的时候。需要用到这个方法。
这个方法就是转换 Button的状态
Selectable这个类 继承 UIBehaviour
还 继承到UIBehaviour, 而且UIBehaviour 多个 UI 组件都回继承它, 具体是干什么的呢?
UIBehaviour 基本上所有的UI控件 都继承到它
生命周期函数 都这里,
以及一些 事件响应函数
继承自 MonoBehaviour 大家都熟悉
MonoBehaviour继承自 Behaviour
之前 很好奇 为什么 MonoBehaviour 里 可以使用Print() 打印函数 原来是在这里
这里还有 协同函数
其实 背后就是一个迭代器实现的。迭代器背后又是怎么实现的呢,其实就是一个状态机,
MoveNext()方法 依托于switch语句,根据状态机的状态,执行不同代码。
MonoBehaviour 是继承自Behaviour的
Behaviour是继承自 compont的
compont: 消耗性能的BroadcastMessage 名声 很差
最后就是UnityEngine 里的Object 基类了
Button——Selectable——UIBehaviour(生命周期函数)——Behaviou——Compoent——Object
重写思路,射线分为 射线进入, 射线停留,射线离开
因此 写3个方法 就可以了
事件 传递UML 类图(借助松阳大神的)
ClickHandler 响应 Click
OnFinishSubmit 这个方法就是 协程,具体就是 点了按钮之后回由个渐渐变色的过程。
最后再梳理一遍 Button
Button 继承的类, 事件系统是基于Unity的, 在移除 事件的时候,通过反射去对比
一个 无参 无返回 委托。
这里的UnityEventBase 类 从当一个中介者的角色,
移除监听 事件时,会调用InvokableCallList 类里的RemoveListener。
RemoveListener方法会调用BaseInvokableCall的 Find方法
这里的UnityEvent 在移除 事件时,会通过反射,取得MethodInfo 再去 对比。
这里不废话c#反射机制了。
EventSystem
优缺点。每次添加 监听 事件时,并没有对应的 事件码, 这样查找就要去 每个通过反射的方式去查找,比较消耗性能,而且添加 每个按钮响应事件 应该 ,给个事件Id ,才知道是哪个事件被触发了。管理很不方便。
下面是 重写 射线Button
public class RayButton : Button
{
public UnityEngine.Events.UnityEvent MenuUIEvent;
/// <summary>
/// 视线进入
/// </summary>
public virtual void RayEneter()
{
DoStateTransition(SelectionState.Highlighted, false);
}
/// <summary>
/// 视线停留
/// </summary>
public virtual void RayStay()
{
ReSetButtonState();
}
/// <summary>
/// 视线离开
/// </summary>
public virtual void RayExit()
{
DoStateTransition(SelectionState.Normal, false);
}
public virtual void TriggerEvent()
{
onClick.Invoke();//调用下 Click事件
DoStateTransition(SelectionState.Pressed, false);
}
/// <summary>
/// 事件完成
/// </summary>
public virtual void ReSetButtonState()
{
DoStateTransition(SelectionState.Highlighted, false);
}
}