![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9EERPlXRq5keRRVT3V1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQjN1IDMzYTM0ATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
//15.輸入處理---------------------------------------------------------------------------------------------
繼承關系:
BaseInputModule<---PointerInputModule<----TouchInputModule
BaseInputModule<---PointerInputModule<----StandaloneInputModule
函數調用關系:
EventSystem.Update()---子類.Process()---子類.ProcessMouseEvent()或 子類.ProcessMouseEvents()---子類.GetMousePointerEventData()
EventSystem.Process() 多态.
輸入管理: EventSystem物體上的Standalone Input Module,TouchInputModule元件
//16. 射線檢測-------------------------------------------------------------------------------------------
繼承關系:
BaseRaycaster<---PhysicsRaycaster<---Physics2DRaycaster
BaseRaycaster<---GraphicRaycaster
函數調用關系:
EventSystem.RaycastAll()---子類.Raycast()---EventSystem.RaycastComparer()
EventSystem.Raycast() 多态. 進行射線檢測.
射線管理: Canvas畫布上的Graphic Raycaster元件
[RequireComponent(typeof(Canvas))]
public class GraphicRaycaster : BaseRaycaster
{...}
這個腳本必須挂在Canvas上.UI元素必須具有繼承自Graphic的元件.也就是可視的UI元素.
GraphicRaycaster元件的成員屬性:
Ignore Reversed Graphic 忽略反方向圖形. 即.圖形面對前方時.才參與射線檢測.
Blocking Objects 屏蔽對象
渲染模式不為ScreenSpaceOverlay時起作用.屏蔽指定類型的對象.使他們不參與射線檢測.
None 不屏蔽任何實體對象
TwoD 屏蔽2d實體對象.(具有2d碰撞體的對象)
ThreeD 屏蔽3d實體對象.(具有3d碰撞體的對象)
All 屏蔽所有實體對象
Blocking Mask 屏蔽層(layer)
渲染模式不為ScreenSpaceOverlay,且locking objects不為None時起作用.
使屏蔽對象(Blocking objects)的物體,不參與射線檢測.
注意:添加的碰撞器大小要和物體一樣大.或者比物體本身大.建立的碰撞體預設是長寬都是1.狠小狠難點中.
射線穿透的順序:
EventSystem.cs中
射線處理,是把所有的裝到連結清單裡.然後排序.
public void RaycastAll(PointerEventData eventData, List<RaycastResult> raycastResults)
{
raycastResults.Clear();
var modules = RaycasterManager.GetRaycasters();
for (int i = 0; i < modules.Count; ++i)
{
var module = modules[i];
if (module == null || !module.IsActive())
continue;
module.Raycast(eventData, raycastResults);
}
raycastResults.Sort(s_RaycastComparer);
}
排序規則函數 RaycastComparer
private static readonly Comparison<RaycastResult> s_RaycastComparer = RaycastComparer;
private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs)
{
if (lhs.module != rhs.module)
{...}
if (lhs.sortingLayer != rhs.sortingLayer)
return rhs.sortingLayer.CompareTo(lhs.sortingLayer);
if (lhs.sortingOrder != rhs.sortingOrder)
return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
if (lhs.depth != rhs.depth)
return rhs.depth.CompareTo(lhs.depth);
if (lhs.distance != rhs.distance)
return lhs.distance.CompareTo(rhs.distance);
return lhs.index.CompareTo(rhs.index);
}
射線穿透排序
EventSystem.RaycastComparer
對射線穿透的所有未屏蔽的物體進行排序
1. 如果Canvas指定了不同錄影機,則按錄影機深度排序.
2. 按sortOrder順序排序
3. 按renderOrder順序排序.
4. 按depth排序.凡是繼承自Graphic的類都有depth屬性.在PhysicsRaycaster,Physic2DRaycaster兩種射線模式下,該值為0.
5. 按distance順序排序.射線發出點到物體的具體.
6. 按index順序排序. 不管是哪種射線模式,或者是混合射線模式,都會将射線碰撞到的UI物體放入一個連結清單或者數組,這裡的index就是他的下标索引值.
元件Canvas Group. 可以管理Canvas.也可以控制Canvas内UI元素.
屬性:
alpha 透明度
interactable 是否可互動
Blocks Raycasts 控制是否穿透
Ignore parent group是否忽略父物體的Canvas Group元件效果.
//17. 事件分發-------------------------------------------------------------------------------------------
函數調用關系:
BaseInputModule.FindFirstRaycast (...)取出射線碰撞到的第一個物體,進行事件處理.
ExecuteEvents.ExecuteHierarchy (...)從篩選出的第一個物體自身開始,一級一級往上擷取父物體.直到有元件(實作了該事件接口的元件)接受事件為止.
protected static RaycastResult FindFirstRaycast(List<RaycastResult> candidates)
{
for (var i = 0; i < candidates.Count; ++i)
{
if (candidates[i].gameObject == null)
continue;
return candidates[i];
}
return new RaycastResult();
}
public static GameObject ExecuteHierarchy<T>(GameObject root, BaseEventData eventData, EventFunction<T> callbackFunction) where T : IEventSystemHandler
{
GetEventChain(root, s_InternalTransformList);
for (var i = 0; i < s_InternalTransformList.Count; i++)
{
var transform = s_InternalTransformList[i];
if (Execute(transform.gameObject, eventData, callbackFunction))
return transform.gameObject;
}
return null;
}
測試:
//腳本 rayTest.cs
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class rayTest : MonoBehaviour ,IPointerClickHandler
{
public void OnPointerClick (PointerEventData eventData)
{
Debug.Log (name);
Debug.Log (eventData.pointerCurrentRaycast.gameObject);
}
}
射線第一個掃到的是Text1物體但是他上面沒有實作點選事件接口.
是以從Text1開始一級一級找父物體看看父物體祖宗物體上有沒有實作這個事件
找到Button上面rayTest腳本中有實作 IPointerClickHandler點選事件接口.
是以就調用這個事件的響應函數OnPointerClick (...)