通常我们为对象附加一个脚本组件,脚本组件只要加此鼠标处理事件方法,这个对象就有了点击事件了:

void OnClick() {
Debug.Log("onclick");
}
可为什么我只要给一个对象附加个脚本,脚本中写此OnClick方法,当我们点击按钮时他就会去执行OnClick方法呢?unity是怎么把他们联系起来的呢?还有除了OnClick事件,还有没有其他事件可以像OnClick事件一样被我们使用,例如:OnDoubleClick,OnHover,OnPress等
答案就在UICamera里面,这个脚本是附在Camera对象上的,有哪些事件我们可以用的,UICamera都告诉我们了,如下:

这些都是大家很常用的事件,所以就不一一解释了!有哪些事件我们可以调用,这个问题解决了,接下来看,附加到对象上的脚本中的事件(以上所列出的事件)是如何被执行的?接下来我们就来看下UICamera是如何对这些事件进行处理的!

在UICamera里面最先执行的就是Awake方法,所以我们先从Awake方法看起:

可以看出Awake方法主要的功能就是判断设备类型,从而确定你是使用的是鼠标还是触摸方式,但我们通常都是用电脑去设计游戏,所以以上的判断都没有被执行,而useMouse和useTouch字段默认都为true,所以这两个字段的值不变,接下来看Update方法(Start方法没什么好说的),当执行到update中的一段代码时,如下:

    // Process touch events first
if (useTouch) ProcessTouches();
else if (useMouse) ProcessMouse();

因为useTouch为true,所以程序回去执行 ProcessTouches方法,这个方法主要是对触屏事件方法的响应,转到ProcessTouches方法,运行到这句话:for (int i = 0; i < Input.touchCount; ++i),这句话Input.touchCount为0,因为我们操作电脑只能通过鼠标,根本不存在触屏操作,所以Input.touchCount为0,程序继续执行下面的

if (Input.touchCount == )
{
if (useMouse) ProcessMouse();
#if UNITY_EDITOR
else ProcessFakeTouches();
#endif
}

如果没有触屏事件,那么就会去执行鼠标事件,也就是去执行ProcessMouse方法去,转到ProcessMouse方法,里面有这么一段代码:

        bool isPressed = false;
bool justPressed = false; for (int i = ; i < ; ++i)
{
if (Input.GetMouseButtonDown(i))
{
currentScheme = ControlScheme.Mouse;
justPressed = true;
isPressed = true;
}
else if (Input.GetMouseButton(i))
{
currentScheme = ControlScheme.Mouse;
isPressed = true;
}
} // No need to perform raycasts every frame
if (isPressed || posChanged || mNextRaycast < RealTime.time)
{
mNextRaycast = RealTime.time + 0.02f;
if (!Raycast(Input.mousePosition)) hoveredObject = fallThrough;
if (hoveredObject == null) hoveredObject = genericEventHandler;
for (int i = ; i < ; ++i) mMouse[i].current = hoveredObject;
}

当我们点击按钮时,isPressed就会为true,而mNextRaycast 永远<RealTime.time,所以内部的代码一直会被执行,也就是说一直执行里面的Raycast方法(即我们所知的发射线),转到Raycast方法去,在Raycast方法里面,他会判断你当前选择的EventType,有两种选择:World 表示按被击中点的距离排序执行一个物理射线,UI表示按部件深度排序执行一个物理射线,通常我们选择的是UI,因为对象的层次我们通常是按depth来设计的,在 i f (cam.eventType == EventType.UI) 里面他会执行Physics.RaycastAll ,也就是发出射线,并把击中的对象赋给hoveredObject(hoveredObject = hit.collider.gameObject),RayCast的作用差不多就是找到被击中的对象,赋给hoveredObject,回过头来,因为hoveredObject对象保存的是被击中的对象,在ProcessMouse方法里for (int i = 0; i < 3; ++i) mMouse[i].current = hoveredObject;把此对象付给了mMouse[i],for循环之所以为3次,因为鼠标有三个键,左键,滚轮键,右键,代码继续执行

        // Process all 3 mouse buttons as individual touches
for (int i = ; i < ; ++i)
{
bool pressed = Input.GetMouseButtonDown(i);
bool unpressed = Input.GetMouseButtonUp(i); if (pressed || unpressed) currentScheme = ControlScheme.Mouse; currentTouch = mMouse[i];
currentTouchID = - - i;
currentKey = KeyCode.Mouse0 + i;
if (pressed || unpressed)
// We don't want to update the last camera while there is a touch happening
if (pressed) currentTouch.pressedCam = currentCamera;
else if (currentTouch.pressed != null) currentCamera = currentTouch.pressedCam; // Process the mouse events
ProcessTouch(pressed, unpressed);
currentKey = KeyCode.None;
}

这里可以看到,射线击中的对象被赋给了currentTouch对象了,当鼠标按下时,pressed表示是否按下,unpressed表示鼠标是否抬起,当我们点击按钮知道完成,pressed和unpressed值会经历这样的变化:True,false -> false true,程序执行到ProcessTouch方法,因为我们是点击事件,所以此方法内部的Notify(currentTouch.pressed, "OnClick", null)这段代码会被执行,继续执行Notify方法:

static public void Notify(GameObject go, string funcName, object obj)
{
if (mNotifying) return;
mNotifying = true; if (NGUITools.GetActive(go))
{ go.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver); if (genericEventHandler != null && genericEventHandler != go)
{
genericEventHandler.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver);
}
}
mNotifying = false;
}

内部是调用对象的SendMessage方法的,对SendMessage方法不懂得,可以参照这篇文章:

http://www.cnblogs.com/MrZivChu/p/sendmessage.html

就此就完成了整个onclick方法的执行了,因为Update方法是一直执行的,所以UICamera脚本会一直发出射线来检测鼠标或者触屏事件,从而执行相应的方法,原理大概就是这样!

以上是个人的总结,如有不当,希望大家多多批评指正!

最新文章

  1. MarkdownPad2.5 注册码
  2. docker创建镜像
  3. icp算法基本思想
  4. easyui layout 收缩的bug
  5. Android 签名(5)用命令签名和用IDE签名
  6. centos git版本服务器配置
  7. XStream简单使用01——xml和Ojbect互转
  8. MFC弹出模拟对话框
  9. UESTC_Sliding Window 2015 UESTC Training for Data Structures&lt;Problem K&gt;
  10. springBoot系列教程01:elasticsearch的集成及使用
  11. Centos7安装ES 和 Docker搭建ES
  12. This is probably because there is no OLE editor registered against the type of file you were trying to open.
  13. 树莓派控制高电平蜂鸣器(c语言+新手向)
  14. kettle 6.1 日志查询
  15. Maven - 实例-4-依赖传递
  16. 【基础】selenium中元素定位的常用方法(三)
  17. [Hanani]JAVA大数相关学习记录
  18. C#中Task的使用简单总结
  19. uboot常用命令详解
  20. Django 缓存、信号

热门文章

  1. java 使用hashmap一个键对应多值的方法
  2. 【BZOJ4487】[JSOI2015] 染色问题(高维容斥)
  3. 模拟停车POJ(3505)
  4. 2017.10.29 C/C++/C#程序如何打成DLL动态库
  5. GDB调试手册[转]
  6. Python 二进制 八进制 十进制 十六进制
  7. data-ng-init 指令
  8. C#静态成员和非静态成员
  9. ADO.net中常用的对象有哪些?
  10. Colours–颜色库,包含100种预定义的颜色和方法