c调用按钮点击事件_Unity3d---对UI事件接口的一些测试和机制(坑)的总结
開文來記錄一下自己摸索到的UI事件接口的一些運作機制(坑),就不贅述具體怎么使用這些事件接口了(不做教學...),本文主要是記自己發現的一些坑點
主要針對于在復雜的UI嵌套關系下,鼠標指針和拖拽操作的事件接口的調用關系,一些容易出錯的地方進行記錄
歡迎各路神仙留言指正,若能不吝賜教,鄙人先謝為敬
版本:Unity 2019.3.0
emmmmmm
怎么好像之前Unity2018的跨父對象層級的Drop方法還無法正常調用來著,做背包系統的時候真的坑死了,現在2019這個坑是被官方填了?
1.還是提一下什么是UI事件接口
在UGUI中通過 using UnityEngine.EventSystems;
可以讓繼承自Mono的腳本實現一些豐富的事件接口,這些被實現接口方法會在進行UI交互的一些特定的行為出現時被調用
主要包括Point鼠標指針操作,Drag/Drop拖拽操作,Select點選操作,Input鼠標鍵盤輸入類
UI事件接口主要用于UI上的一些物體(Image,Button一類),也可以應用到場景中一些3D物體
UI事件接口能夠在 PC鼠標 和 觸屏 兩種操作模式下被正確的使用
在使用中UI事件接口與EventTrigger實現的交互事件區別在于,當某個UI物體需要被設計為一個對象,在針對它的特定的交互行為出現時調用該對象自身的一些方法,實現一些交互功能時,應使用UI事件接口的實現方法,將腳本掛在該物體上。而當某個UI物體不需要被設計為一個對象,在針對它的特定的交互行為出現時,需要去調用別的物體上某個組件的方法來實現一些交互功能時,應使用EventTrigger的實現方法,添加EventTrigger,添加交互行為并綁定別的物體上特定組件的特定方法
UI事件接口和EventTrigger能被正確調用的預備條件一致,即:
針對UI物體時,場景中應創建EventSystem,UI物體的RectTransform需要有一定的寬高
針對3D物體時,場景中應創建EventSystem,攝像機應添加Physics Raycaster組件,3D物體需要有Collider組件
2.準備一下測試
場景物體擺放即父子關系
分別給兩個Panel添加一個名為 Test_IEP的腳本
給所有 Button 和 Image 都添加一個名為 Test_IEC的腳本
3.IPointer 鼠標點擊事件接口測試
---3.1 父子均實現 IPointerDownHandler, IPointerUpHandler (出現覆蓋問題)
using using------3.1.1 分別點擊Panel沒有被子對象覆蓋的區域,和子對象
我們點擊Panel沒有被覆蓋子對象的部分和子對象在父子均實現IPointerDownHandler, IPointerUpHandler時,點擊子對象覆蓋住父對象的范圍內時,只觸發子對象的接口方法
------3.1.2 同級別下有遮擋時點擊重和部分
同級別均實現IPointerDownHandler, IPointerUpHandler,UI物體有重和時,點擊重和部分,僅觸發最上層被點擊到的UI對象的接口方法
補充一下:Hierarchy菜單,UI物體中越靠下的物體,才是越接近最上層的
---3.2 僅父對象實現 IPointerDownHandler, IPointerUpHandler (按鈕是個特例)
using using 點擊按鈕,父對象的接口方法沒有被觸發但點擊Image正常觸發父對象的接口方法僅父對象實現 IPointerDownHandler, IPointerUpHandler 時,點擊子對象中的按鈕仍無法觸發父對象的接口方法(可以理解為按鈕組件本身就有IPointer接口)依然覆蓋掉了點擊向父對象的傳遞。但點擊到子對象中Image的一類本身不具有交互性的子對象,可以正常觸發父對象的接口方法
我們取消按鈕的可交互性,點擊按鈕依然無法觸發父對象的接口方法將按鈕組件UnEnable時,點擊按鈕能夠觸發父對象的方法---3.3 重合時僅下層實現 IPointerDownHandler, IPointerUpHandler (遮擋依然存在)
不論下層是否是按鈕還是Image,點擊重合部分,下層物體實現的接口方法都不會被觸發
自然上下層都實現肯定只調用上層實現的接口方法
---3.4 只實現IPointerUpHandler時(無法正常被調用)
只實現IPointerUpHandler根本無法正常調用,必須實現IPointerDownHandler,才能正常傳遞,調用IPointerUpHandler的接口方法
---3.5 IPointerClickHandler(與3.1,3.2出現的情況類似)
參見3.1 和 3.2 測試結果類似,出現子對象覆蓋,同級只觸發最上層,以及按鈕的特例覆蓋效應
4.Drag/Drop 拖拽接口測試
先補充幾點:
1.UI事件接口的onDrag方法在開始拖動后,如果中途停止拖動(不松開鼠標但不移動)不會被調用,而我們有測試過onMouseDrag方法,開始拖動后即使中途拖動停止,依然會被調用
2.即使在極端狀況下,IPointerDownHandler 也一定會先于 IBeginDragHandler被調用
3.可以通過eventData.pointerDrag.name 獲取拖動啟發的對象,并經常結合onDrop使用
4.IBeginDragHandler,IDragHandler,IEndDragHandler調用時均調用啟發拖拽的物體,而IDropHandler是拖拽到的物體(結束拖拽是鼠標停留的物體)
5.通過eventData.Dragging可以判斷是否處于拖拽狀態
---4.1 父子對象 均實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler(依然有遮擋問題,跨層級拖拽正常)
using using panel_1內部panel_1到panel_2pane_1到panel_2中的Buttonpanel_1到自己內部的buttonpanel_1內部button到panel_1button到重合部分panel_1中的button到panel_2panel_1中的button到panel_2中的buttonpanel_2到重合部分重和部分到button_1父子對象 均實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler時,注意遮擋問題,子對象對父對象的遮擋,重和部分的遮擋,以及onDrop一定先于endDrag調用。其他沒有什么特別的地方
---4.2 僅父物體實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler(這次誰也擋不住了)
using using 我們從panel_1中的button開始拖拽,拖拽到panel_2中的button上松開??梢钥吹礁肝矬w的Drag/Drop接口方法被調用僅父物體實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler時,從子物體覆蓋父物體的區域開始拖拽或結束拖拽,不論是Button或Image。父物體的接口方法都被正常調用
---4.3 重合時都實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler(依然存在遮擋)
無論是從重合部分開始拖拽還是拖拽到重合部分,僅調用上層實現的方法
---4.4 重合時僅下層實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler(依然存在遮擋)
無論上下層是button或Image,接口方法都無法被正常調用
結合4.2和4.4的一個坑:
重合時,下層實現所有Drag/Drop,上層什么都不實現,父物體實現所有Drag/Drop。從重合部分拖拽,調用父物體的Drag/Drop
---4.5 不完全實現IBeginDragHandler,IDragHandler,IEndDragHandler,IDropHandler(注意傳遞)
好吧直接寫好了...
IBeginDragHandler可以不實現,依然正常調用IDragHandler
但如果反過來不實現IDragHandler,則無法正常調用IBeginDragHandler
想要正常調用IEndDragHandler, IDropHandler,則必須實現IDragHandler
5.IPointerEnterHandler,IPointerExitHandler
emmmmmm
不詳述了
父子均實現時表現正常僅父物體實現,子物體不遮擋僅實現IPointerExit可以被正常調用6.
這里其實還可以測一下
Button自身原有的click事件綁定器和IPointerClick事件接口同時使用時的情況
以及EventTrigger和UI事件接口同時使用時的情況
不過就算了吧,一來太占篇幅。二來根本沒有意義...因為沒有理由要同時使用兩種及以上的事件觸發方法
7.總結和應用
---7.1 總結一下
------7.1.1 唯一性、遮擋、搜索判斷模式
唯一性:
在特定的交互行為出現時,UI事件的調用,無論是事件接口還是本身具有交互性的UI物體
事件的調用和傳遞具有唯一性
即特定交互行為只觸發唯一一個物體所實現的事件接口方法,或是展現其對應的交互性(Button的點擊,Scrollbar的拖拽)
由于唯一性的存在,UI事件的調用具有了遮擋問題
遮擋:
Point鼠標指針操作,Drag/Drop拖拽操作都存在遮擋問題:
同級別時,上層對下層的遮擋,即使上層物體沒有實現接口,依然能夠在重合部分阻擋下層實現的接口方法的調用
而跨父子物體時,對于父物體實現IPointer或是IDrag方法
普通的本身不具有交互性的組件像是 Image Text 它們不會在覆蓋住父物體的部分阻擋父物體接口方法的調用
而具有交互性的組件,則會根據其本身具有的交互性,阻擋對應的父物體實現的UI事件接口方法被調用
比如上面提到的Button本身交互性需要鼠標的點擊和抬起,但不需要鼠標的拖拽,因此,子物體Button能夠阻擋父物體實現的Pointer鼠標指針事件接口方法被調用,但不會阻擋Drag/Drop事件接口的調用
而對于像Scrollbar(滑動條),這樣的既需要點擊交互,又有拖拽交互的組件,則會同時阻擋父物體的Pointer鼠標指針和Drag/Drop事件接口
我們還發現了有趣的,具有揭示性的一點:
我們添加了一個滑動條,并這樣拖拽了一下父物體Panel的IBeginDragHandler,IDragHandler,IEndDragHandler都被阻擋了,但居然調用了父物體Panel的OnDrop方法
其實不難猜到(盡管我沒去翻過這部分被公開的源碼),Unity的UI系統,那些本身具有交互性的組件,就是使用了這些UI事件接口來實現的交互性
搜索判斷模式:
當出現交互時,是從最低一級的最上層的子物體開始依次到最高一級最上層的父物體,判斷調用事件接口方法的過程中,只跨父子層級尋找,同父子層級只看最上層的物體有沒有對應的方法
坑點1.重合時,下層和父物體實現,上層不實現不具有對應交互性需求,重合部分會調用到父物體的接口方法,而不是下層。因為發現上層沒有就會跨父子層級尋找被實現的接口,而不是在同父子層級下依次尋找不同層
RectTransform.SetAsLastSibling(); (你懂的,這個方法就很有用了...)
坑點2.因為跨父子層級尋找,導致同父子層級時,上層不實現一定在重合部分阻擋下層實現的接口方法被調用
------7.1.2 注意事件的傳遞問題
只實現IPointerUpHandler根本無法正常調用,必須實現IPointerDownHandler,才能正常傳遞
IBeginDragHandler可以不實現,依然正常調用IDragHandler。但如果反過來不實現IDragHandler,則無法正常調用IBeginDragHandler。想要正常調用IEndDragHandler, IDropHandler,則必須實現IDragHandler
僅實現IPointerExit可以被正常調用
---7.2 一個應用
充分理解,才能更好的應用
在背包系統中我們希望實現一次性全部拾取和精確拾取
一次性全部拾取:
精確拾取:
我們將這個動態生成的物體,最高一級的父物體上的腳本中,通過Drag/Drop方法實現拖拽放入背包的操作
我們在其子物體上,用一個Button,添加一個腳本,通過IPointerDown方法告知父物體需要開啟精確拾取設置面板,且從Button拖拽時不阻擋父物體的Drag/Drop方法,能夠正常拾取
ok這個Button還可以設置一下Pressed Color 點擊的時候變色來提示進行精確拾取
-----The End-----
/*
今天是在復習Unity的UI系統,翻到了以前寫的背包系統,之前寫的時候UI事件接口這里被坑了好久,雖然解決了問題,但沒有進行系統的測試,也沒有留下什么總結
今天測試了一下,發現好像沒有那么簡單,就趕緊來開文,一邊測試一邊記錄總結,到現在寫完這篇文章,自己也才總結清楚
嗯嗯,感覺醬紫挺不錯的,印象更深刻了,以后忘記了還能回來看看這篇文章
ok復習大英復習大英,明天要考試了的說...
歡迎各路神仙能夠留言指正,或是賜教一些我不知道的點,鄙人先寫為敬
*/
總結
以上是生活随笔為你收集整理的c调用按钮点击事件_Unity3d---对UI事件接口的一些测试和机制(坑)的总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: datagridview滚动条自动滚动_
- 下一篇: response.sendredirec