unity ugui訊息透傳

2022-02-26 15:21:48 字數 3820 閱讀 6085

公司要做乙個這東西。

a是滑動區域,scrollrect元件。

b是各種選項。

c是拾取到滑鼠(或觸點)的選項。

d是拖放區域。

大概要求是這樣。

因為b的條目很多,放在a裡可以滑動檢視。如果要選擇乙個b,需要長按b,待時間足夠之後生產乙個新的c。拖動到d區域釋放,則給d新增乙個節點。其他區域則取消。

如果按住b的時間不夠長,又動了滑鼠(或觸點),則當前滑動操作由a響應,產生a的滑動效果。

這裡涉及到乙個訊息透傳的問題。

解釋一下自己在做的過程中採用的2個方案以及各自問題。

涉及的函式有以下幾個:

onpointerdown

onpointerup

ondrag

將最終結果放這裡,你要不願看完,直接拿東西走人。

訊息重置**。

eventdata.pointerenter = m_scro.gameobject;

eventdata.pointerpress = m_scro.gameobject;

eventdata.rawpointerpress = m_scro.gameobject;

eventdata.pointerdrag = m_scro.gameobject;

m_scro.onbegindrag(eventdata);

方案1:

win7+unity531。

剛開做的時候使用的531版本。在這個版本上做了些測試。得到以下資料:

使用eventtrigger,只有最上面的ui可以獲得輸入並呼叫eventtrigger設定的函式。

如果不使用eventtrigger,則需要自己繼承一些類。需要什麼類可以在eventtrigger裡根據你需要的函式進行查詢。比如你在eventtrigger中使用了pointer up訊息。直接在unity文件的指令碼分類下查詢pointerup即可找到這個訊息由哪個類分發,繼承一下,自己重寫一下這個函式就好。

如果不使用eventtrigger,採用繼承訊息類的方式工作,那麼ui是否響應輸入由

raycast target

這個選項決定。(使用

eventtrigger的情況下沒測,因為那個滿足不了需求了。

)當你對乙個ui進行了操作之後,如果不做任何修改和特別處理,預設情況下,所有滑鼠(或觸點)操作均由這個ui控制項接收。比如先在這個控制項內

onpointerdown,然後按住滑鼠不放,滑鼠移動到別的ui上,再放開,

onpointerup函式依舊呼叫的是

onpointerdown時的ui。

如果只繼承了

onpointerdown和

onpointerup函式。則當

onpointerdown進入之後,如果產生了drag輸入,則會產生

onpointerup

事件。再使用繼承訊息類及以上資訊的情況下,a可以在即使點中b的情況下正常拖動。而且b的函式照進。

拖放操作響應函式是ondrop,遵循第四條規則。但是如果我希望別的控制項能夠響應ondrop,只需要把當前移動的這個ui的raycast target設定為false就好。(這裡其實已經是一種訊息透傳了)

根據以上資訊,於是我做了第一套方案:

大致如下:

根據以上思路,大部分情況都解決了。只是有乙個問題。全域性管理器的觸點判定是在update裡的。而ondrop是觸發的。邏輯是ondrop響應之後做自身的處理,並通知全域性管理器清空m_drag一防止被destroy。但並不知道當前這次的訊息處理是在update之前還是之後。如果在當前幀,滑鼠觸點已經釋放,先進入update,則在ondrop被觸發之前,m_drag就會被update先給destroy掉。而如果ondrop先呼叫,則可以確保正常。

在531下,測試結果顯示,當前幀的輸入處理在update之前,於是方案一完成。

合併**,對方用的535,於是我只好跟著公升,這一公升,壞了。拖動出問題了,拖出來放不進去了。

一檢查,ondrop跑到update後面執行去了。

這樣一來,沒有合適的地方可以判斷滑鼠(或觸點)的釋放。於是只好考慮用onpointerup好了。可是onpointerup在控制項被拖動的時候就會呼叫啊,根本沒有機會或者說合適的地方可以產生onpointerup函式的呼叫,於是又做了一些測試如下:

如果只繼承了onpointerdown和onpointerup函式。則當onpointerdown進入之後,如果產生了drag輸入,則會產生onpointerup事件。但如果再繼承ondrag,則會進入ondrag事件而不是onpointerup。onpointerup將會在滑鼠彈起(或觸點被釋放)時產生。

這是方案一第五條的補充。也是加入ondrag之後逐步發現的,中間也除錯了很久,出了很多麻煩事情。

有了這條,似乎一切都沒問題了。於是加上,測試,一切ok。似乎完成了。然後我發現a在點到b的時候不再獲取輸入了。也就是說當我點到b的時候,a不能被滑動。drag訊息傳給了b的指令碼。

注:到這一步,我並沒有嘗試用關閉raycast target的方法來解決。原因有2:

我需要onpointerup,如果關閉,onpointerup想來是不會響應的,因為如果能通過關閉raycast target來將drag傳給a,那說明b已經不再獲取輸入了。

我需要徹底解決訊息透傳的問題,萬一還有其他模組也會遇到類似的情況呢?

於是無法避免,考慮到以後也可能要用,只好來硬的,一定要解決訊息透傳的問題。

現在思路有2:

獲取到我要控制的元件,在當前ui內,將輸入資訊傳給這個要控制的元件,再修改。(這裡就是在b內獲取到drag資訊,將drag資訊傳遞給a物件,以控制a的滑動)

將輸入訊息重置。或新建乙個,或將我希望獲取輸入的元件放進去。

翻了好久。eventsystem、baseeventdata、pointereventdata都翻過了,沒有發現。

於是採用第一條思路。第一條思路也很容易。也許用在別的ui上已經沒問題了。

但最讓我傷心的是scrollrect這個元件,如果你通過外部的方式(就是直接指令碼改座標)修改其容器的座標,會彈回去。於是又去查怎麼取消scrollrect的回彈操作。一系列處理下來,似乎也能滿足要求。然而因為第一次使用ugui,並沒有發現有什麼好的方案能讓我在訊息透傳的時候讓scrollrect不彈回,而當我訊息透傳結束之後再開啟彈回。就算有,介面上的小跳動,也無法直視。

於是又想。還是再看看,再嗖嗖,看看能不能重置訊息。畢竟這才是正道。

然後解開了。怎麼發現的我就不說了,純屬運氣。我在檢視eventsystem這個場景物件的時候,發現有個pointerdrag的物件。正好是我拖動的物件,我在想,如果改掉他會怎麼樣?

於是指令碼裡一搜pointerdrag,在pointereventdata類下。這就是訊息函式傳進來的引數啊。於是將pointerdrag直接改成了a,好的,一切工作正常,就是還會跳動。推測可能是因為中途突然加入輸入資訊導致,沒有前提條件。於是將scrollrect的drag函式查詢了一番,正好有個onbegindrag,加上,一切就正常了。

eventdata.pointerenter = m_scro.gameobject;

eventdata.pointerpress = m_scro.gameobject;

eventdata.rawpointerpress = m_scro.gameobject;

eventdata.pointerdrag = m_scro.gameobject;

m_scro.onbegindrag(eventdata);

這就是訊息重置。

就是當按住b的時間不夠,產生了拖動,要將當前拖動訊息交由a處理的核心**。

其他訊息相信也應該類似。

透傳訊息和非透傳訊息

目前的訊息推送方式主要有兩種 通知和透傳。什麼是透傳?透傳即是透明傳送,即傳送網路無論傳輸業務如何,只負責將需要傳送的業務傳送到目的節點,同時保證傳輸的質量即可,而不對傳輸的業務進行處理。透傳訊息,就是訊息體格式及內容,對於傳遞的通道來說是不去過問的,通道只負責訊息的傳遞,對訊息不做任何處理,當客戶...

APP訊息推送 通知和透傳

目前市場上的訊息推送方式有兩種 通知和透傳。什麼是透傳?透傳即是透明傳送,即傳送網路無論傳輸業務如何,只負責將需要傳送的業務傳送到目的節點,同時保證傳輸的質量即可,而不對傳輸的業務進行處理。透傳訊息,就是訊息體格式及內容,對於傳遞的通道來說是不去過問的,通道只負責訊息的傳遞,對訊息不做任何處理,當客...

mobile 點透 傳透

點透 傳透 pc 的 click 事件 在移動端,會有 300 ms 的延遲。就是因為避免和手機雙擊行為發生衝突 當點選 非文字覆蓋區域 時,盒子正常消失。當點選 文字區域時,頁面發生跳轉。無論點選哪個區域,只要是點選盒子,盒子都消失,而不影響 a click 事件監聽,缺點 pc 端的 click...