天天看點

Unity 中 UGUI 事件順序

Unity 中 UGUI 事件順序

//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);

    }

}
           
Unity 中 UGUI 事件順序

射線第一個掃到的是Text1物體但是他上面沒有實作點選事件接口.

是以從Text1開始一級一級找父物體看看父物體祖宗物體上有沒有實作這個事件

找到Button上面rayTest腳本中有實作 IPointerClickHandler點選事件接口.

是以就調用這個事件的響應函數OnPointerClick (...)

繼續閱讀