公司要做乙個這東西。
a是滑動區域,scrollrect元件。
b是各種選項。
c是拾取到滑鼠(或觸點)的選項。
d是拖放區域。
大概要求是這樣。
因為b的條目很多,放在a裡可以滑動檢視。如果要選擇乙個b,需要長按b,待時間足夠之後生產乙個新的c。拖動到d區域釋放,則給d新增乙個節點。其他區域則取消。
如果按住b的時間不夠長,又動了滑鼠(或觸點),則當前滑動操作由a響應,產生a的滑動效果。
這裡涉及到乙個訊息透傳的問題。
解釋一下自己在做的過程中採用的2個方案以及各自問題。
涉及的函式有以下幾個:
onpointerdown
onpointerup
ondrag
將最終結果放這裡,你要不願看完,直接拿東西走人。
訊息重置**。
eventdata.pointerenter = m_scro.gameobject;方案1:eventdata.pointerpress = m_scro.gameobject;
eventdata.rawpointerpress = m_scro.gameobject;
eventdata.pointerdrag = m_scro.gameobject;
m_scro.onbegindrag(eventdata);
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...