因为GVRDemo的光标系统就是用的EventSystem,所以在讲GVRDemo的光标的时候,必须要先对Unity3D的EventSystem系统有所了解。
可以参考http://blog.csdn.net/yupu56/article/details/53010868
了解了怎么使用EventSystem后,接下来简单分析下GVRDemo的光标系统怎么实现的。
关键是从哪里开始入手分析,看一个demo或一大块代码的时候,总是有这个疑问。我一般就从现象入手分析。对于GVRDemo光标系统主要体现在两块。
1.当光标对准立方体的时候,会变成蓝色。
2.当光标对准菜单的时候,菜单会变绿色。
我主要分析立方体的那个,菜单的原理是一样的。
设计到的文件有:
在Main Camera孩子中有GvrReticlePointer:负责画出光标,也就是正常是个小圆点,如果落到一个object上面这个圆的半径变大。
GvrReticlePointerImpl:在GvrReticlePointer文件中被用到了。
在Main Camera里面有GvrPointerPhysicsRaycaster:主要实现了Raycast方法,实现了射线投射,会配合EventSystem使用。它继承方法GvrBasePointerRaycaster类,然后GvrBasePointerRaycaster继承于BaseRaycaster,BaseRaycaster是EventSystem中实现射线投射的基类。
在GvrBasePointerRaycaster中会根据不同的模式产生不同的射线
/// Calculates the ray to use for raycasting based on
/// the selected raycast mode.
protected Ray GetRay() {
if (!IsPointerAvailable()) {
Debug.LogError("Calling GetRay when the pointer isn't available.");
lastRay = new Ray();
return lastRay;
}
Transform pointerTransform = GvrPointerManager.Pointer.PointerTransform;
switch (raycastMode) {
case RaycastMode.Camera:
Vector3 rayPointerStart = pointerTransform.position;
Vector3 rayPointerEnd = rayPointerStart + (pointerTransform.forward * MaxPointerDistance);
Vector3 cameraLocation = Camera.main.transform.position;
Vector3 finalRayDirection = rayPointerEnd - cameraLocation;
finalRayDirection.Normalize();
Vector3 finalRayStart = cameraLocation + (finalRayDirection * Camera.main.nearClipPlane);
lastRay = new Ray(finalRayStart, finalRayDirection);
break;
case RaycastMode.Direct:
lastRay = new Ray(pointerTransform.position, pointerTransform.forward);
break;
default:
lastRay = new Ray();
break;
}
return lastRay;
}
其中的GvrPointerManager.Pointer是在哪赋值的呢?
答案就在GvrReticlePointer类中:
public void SetAsMainPointer() {
GvrPointerManager.Pointer = reticlePointerImpl;
}
reticlePointerImpl的类型是如下类,关于它的介绍如下:
/// Draws a circular reticle in front of any object that the user points at.
/// The circle dilates if the object is clickable.
public class GvrReticlePointerImpl : GvrBasePointer {
大概意思就是它就是画一个光标,当物体被点击的时候,光标变大。
google为什么不用默认的射线投射,很明显因为默认的射线投射是需要有光标点的,用光标点来实现物体的选择,unity默认是没有这个的。
因为其他博客中对于射线的一个说明
系统实现的射线投射类组件有PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster。这个模块也是可以自己继承BaseRaycaster实现个性化定制。
总的来说,EventSystem负责管理,BaseInputModule负责输入,BaseRaycaster负责确定目标对象,目标对象负责接收事件并处理,然后一个完整的事件系统就有了。
在GVREventSystem模块下面有GvrPointerInputModule和GvrPointerManager:
其中GvrPointerManager主要是注册光标的,它里面有方法
/// GvrBasePointer calls this when it is created.
/// If a pointer hasn't already been assigned, it
/// will assign the newly created one by default.
///
/// This simplifies the common case of having only one
/// GvrBasePointer so is can be automatically hooked up
/// to the manager. If multiple GvrGazePointers are in
///