1. 程式人生 > >基於Unity-Ray射線,實現UGUI-Button功能

基於Unity-Ray射線,實現UGUI-Button功能

曾經在專案開發中,遇到有的時候UI不是用UGUI,比如SpriteRenderer,甚至有些專案UI是3D的,也有時候UGUI Button的一些功能不能滿足我們的需求,比如Button的互動是特效或者是幾個UI組成的一種互動方式,那麼UGUI自帶的Button其實並不能滿足我們的需求;

在這裡插入圖片描述

一、思路解析

不管是UGUI的Button思路,還是任何我們常見的Button,其實操作都是一樣的,那麼我們就來解析下UGUI Button的實現機制。

其實,最初我在開發中,我以為UGUI的Button實現機制是通過射線Ray去實現的(好像NGUI是通過射線Ray來實現的),後來我在開發中又發現了,UGUI有可能是通過螢幕座標去識別控制元件的區域,然後來實現Button的操作。

這兩種情況其實都是可以實現的,有好有壞,在有些情況下射線Ray會比螢幕座標識別區域來好,有些情況螢幕座標識別區域會比射線Ray要方便很多,螢幕座標就不用管這個物體是誰,控制元件只需要斷滑鼠位於區域內,就可以執行操作,這個因情況而定。

當然,以上的兩種情況只是我的猜測,因為我還沒有吃透UGUI,估計我瞭解的只是淺層的東西吧,不過我也基於這兩種情況,讓我自己基於UGUI重新寫了一套新的GUI。

Button控制元件,重點需要的事件有下面幾種:

1)、OnEnter(移入)

2)、OnExit(移出)

3)、OnDown(按下)

4)、OnUp(擡起)

5)、OnClick(點選)

以上的五種Button常用的事件,基本上是所有Button公用的事件了,當然還有其他的,比如雙擊(其實就是在指定時間內,執行兩次OnClick)、長按(其實就是OnDown按下多久,也是時間引數)等。

以下實現原理是通過射線Ray來實現的,至於螢幕座標識別控制元件,會在後續其他控制元件(滾動條ScrollBar)在介紹,可能會更好一些。

注:下述說的Button介紹原理,並不是UGUI的Button,而是說用一個Image或者GameObject物體,如何來實現Button的機制。

1、OnEnter原理 OnEnter()原理非常簡單,就是當射線照射到Button時,觸發OnEnter()事件,該事件只會執行一次,也就是移入那一刻觸發。

2、OnExit原理 OnExit()原理,當射線離開已經照射到的Button時,觸發OnExit()事件,該事件同樣執行一次。當移入後移出時觸發。

3、OnDown原理

OnDown()原理,前提是執行OnEnter後,也就是射線照射到Button了,然後在這個Button中按下,則觸發OnDown()事件。

這裡的“按下”,一般是滑鼠的按下(至於哪個鍵按下來觸發這個事件,自己定義即可),同時你也可以是VR裝置的按鍵,也可以是任何其他你所定義的裝置。

這裡就延伸出一個東西了,也就是說輸入端(比如滑鼠、鍵盤、VR裝置、等其他裝置),按下某個鍵,通過按下某個鍵來通知Button,然後就可以觸發這個Button的事件。

4、OnUp原理

OnUp()原理,前提是執行OnDown後,在該Button中執行釋放操作,則觸發OnUp()事件。

這裡的“釋放”,一般是滑鼠按下後,釋放。也可以是其他外裝置某個鍵按下之後的釋放操作。

5、OnClick原理

OnClick()原理,則是OnDown-OnUp。兩個事件的組合。當在照射到的Button中執行OnDown事件後,同時在該Button內也執行了OnUp事件。當這一套事件組在指定Button內執行後,這個操作就屬於OnClick()事件了。

二、實現

在上述中,介紹了Button的原理後,現在我們就需要去如何實現了,我們需要寫兩個指令碼。第一個指令碼是射線控制端(RayController),它是用來發射線,判斷照射到哪個物體,以及一些事件的觸發。第二個指令碼是Button類,也就是提供上述的事件。

Button類 定義上述我們介紹的一些事件。 在這裡插入圖片描述 在這裡插入圖片描述

基於UnityEvent類擴充套件了ButtonEvent,攜帶Int引數,這個引數就是按鍵ID,比如滑鼠左鍵為0,右鍵為1等等。在外設中,基本每一個按鍵都是有ID的,即使是VR裝置。

在定義用於RayController觸發的相關方法。 在這裡插入圖片描述

其他方式也是類似的,在方法內執行事件,用於通知已經註冊在內的事件。

同時在指定Button的Layer層,以及Tag。指定Tag方便射線照射物體時可以更省記憶體去找到指定的Button Layer。如果沒有Tag的話,那麼當射線照射到該Layer時,要想分辨出Buton,必須用GetConponent來判斷是不是Button,如果只執行一次還好,如果每幀都執行,那就會佔記憶體了。 在這裡插入圖片描述 在此,Button類就已經設計完畢了,當然你也可以在Button中新增音訊、IsEnable(Button的啟用)等等。

RayController 射線控制端就相對簡單了,需要注重三個點,第一個點接收【外設鍵按下】、【外設鍵釋放】、【射線照射】。

  • 外設鍵按下 在這裡插入圖片描述

上述的OnButtonPress()方法是用於接收外設鍵的按下處理,當有鍵按下時,判斷此時是否照射到Button(currentButton),如果currentButton不為Null,則執行OnDown方法,並且將鍵ID作為引數進行傳輸。

至於“handIndex!=this._handIndex”這行程式碼則是用於遮蔽射線發射點,比如雙滑鼠、或者VR的兩隻手柄,如果手柄一照射到物體進行按下,那麼應該只觸發手柄一的按下處理,手柄二的一些處理則不應該執行。

  • 外設鍵釋放 在這裡插入圖片描述

OnButtonRelease方法是鍵釋放時的處理,釋放時處理有幾種情況,一種是在在Button中執行了OnDown,但是移動了其他地方,這時只執行釋放OnUp。另一種是在Button中執行了OnDown,在該Button執行了OnUp。那麼OnUp事件還是要觸發,同時還要執行OnClick。因為這一套操作組合成了一個單擊操作。

如果想執行雙擊,那麼只需要在指定時間內接收OnClick次數。

  • 射線處理

    1、定義攝像機和發射源

    發射源需要注意的是,是從哪裡開始發射線,這裡是滑鼠。如果是VR裝置,那麼就是手柄了。一般任何的VR裝置都會有關於手柄座標的介面,這個可以不用擔心。 在這裡插入圖片描述 2、照射指定Layer 在這裡插入圖片描述 通過發射點,照射到指定層,然後判斷照射到的是不是Button,如果是則進行一些處理,如果不是,則進行其他處理。

    3、對Button進行處理 在這裡插入圖片描述 在這裡插入圖片描述

    這裡主要是當照射是Button時,則實現OnEnter,如果照射到同一個則不處理,如果照射到不同的,則把當前的Button執行OnExit。並且設定另一個Button執行OnEnter。這一塊就是邏輯的處理,很簡單。

三、總結

到此,Button的原理介紹就講完了,Button相對來說,比較簡單。只要稍微觀察下Unity的Button就可以知道了。當然上述的Button只是最初形態,在我開發的GUI中,這個屬於Button的基類,通過它我延伸出Toggle、Dropdown、Scrollbar。因為上述的Button是通過射線來做處理的,所以不管是3D物體,還是UGUI中的UI,都是可以適用的。

首頁就是我最終的Button了,根據選擇不同的Button型別(SpriteRender、Image、Object)等來進行操作。同時還有Button組、音訊等等。

下一篇我會介紹Button組、Toggle(開關)的原理。

讀者如果有任何的疑問或意見可以直接關注我的公眾號(Hua灬清)進行詢問,同時每週會推送原創技術部落格。 在這裡插入圖片描述