Unity3D UniRx ReactiveX響應式程式設計初探1 雙擊的檢測
版本:unity 5.6 語言:C#
UniRx版本:5.5
總起:
ReactiveX並不是個新技術,百度上一搜就有很多中文的資料,但唯獨沒有針對Unity的UniRx資料,我這邊就開個坑進行介紹。
Rx由微軟公司進行開發,並於2012年開源,現在支援的語言平臺有20多種。所以什麼是ReactiveX呢?
根據我個人的理解:ReactiveX主要處理時間上非同步的各種操作,使用簡潔的編碼實現需要各種計時器才能完成的功能。
讓我們來結合一個簡單的例子來說一下。
一個例子:
實現的功能是程式能判斷當前的點選是單擊還是雙擊?
在拿到Unity的第一天開始,我就想著Unity本身也沒有提供雙擊,如果想要做一個類似Window雙擊執行檔案的效果該怎麼做呢?後來有過一些思路,不過專案上不需要用到,所以沒實際寫下來。
這次我們來看看我的實現:
// 當前統計到的點選數量 int clickCount = 0; float dTime = 0; float maxDTime = 0.25f; // Update中的實現,所以需要用到dTime來記錄時間 void Update () { if (clickCount > 0) { // 記錄到第一次點選後,開始記錄時間 dTime += Time.deltaTime; // 時間超過了最大時間,列印結果,並重置 if(dTime > maxDTime) { if (clickCount == 1) Debug.Log("單擊"); else Debug.Log("雙擊"); clickCount = 0; } else { // 沒有超過時間的情況下,又發生了一次點選,增加計數器 if (Input.GetMouseButtonDown(0)) { dTime = 0f; ++clickCount; } } } else { // 監聽第一次點選 dTime = 0f; if(Input.GetMouseButtonDown(0)) clickCount = 1; } }
其實實現過程並不複雜。我自己寫了非常多和以上實現類似的程式,心情好用個協程,但是協程也有不方便的地方:無法處理異常、沒有返回值。
回到雙擊功能的實現上來,那麼Rx會怎麼做呢?
請看以下程式碼:
void Start() { // 每一幀執行,點選滑鼠左鍵的時候觸發 var clickStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0)); var obser = clickStream.Buffer(clickStream.Throttle(TimeSpan.FromMilliseconds(250))); //不多說,原理我沒研究,但效果跟我上面的實現一樣 obser.Where(xs => xs.Count >= 2) .Subscribe(xs => Debug.Log("DoubleClick Detected ! Count:" + xs.Count)); obser.Where(xs => xs.Count == 1) .Subscribe(_ => Debug.Log("Once Click")); }
一共6行程式碼,看看結果:
就像執行一個方法一樣,在初始化的時候設定些引數就能完成Update每幀都需要執行的方法。理解上可能有些困難,但他相對我的實現有什麼好處呢?
第一,非常重要,可以非常方便的封裝,寫個工具類放Rx的程式碼放進去,需要的一呼叫就行。不然每次都要去Update中複製貼上程式碼,而且還要考慮到其他在Update中執行的程式碼;
第二,使用Dispose()方法可以隨時取消監聽,不然你還要設定個flag,在Update中每幀判斷flag是否已經為false,然後跳過檢測的程式碼;
第三,程式碼簡潔精悍,我在學C++的時候,有一句話我印象深刻:簡潔是一種美德。嗯,所以我這邊黑一下Java。
以上的三點足以讓我對這個框架心馳神往,我每次在Update中碼上三、四百行程式碼時,我就想著就沒有更加簡潔的實現嗎?直到我現在遇到了UniRx。
當然學習難度比較高,需要一定時間的積累才能寫出類似上面的程式碼。
這個例子先介紹到這,我繼續研究這個UniRx。
個人:
ECS的下一個例子等到我實際用過該框架後,再來帶著實際經驗來講解,有關注的同學需要等一等。然後UniRx又是個大坑(已經開了不知道多少個坑,不過都會填的放心,我會一直做遊戲的),響應式程式設計我也是第一次接觸,Linq我都沒咋寫過,所以理解的障礙又增加了一層。
ECS和UniRx現在都要實際用到,不學做不了功能,只能說是硬著頭皮上。說起來IT技術真正用起來的時候都是一些沒有接觸過的技術,臨時學習整理,儘量去克服,擴充套件知識面的同時,也鍛鍊自己快速掌握新技術的能力。
最近Unity官方說要本地化在徵求大家的意見,我個人反對本地化,因為你看我最近研究的ECS和UniRx都沒有中文,Unity本地化了你去學了,那下一個新的技術難道也要等到本地化了再學?恕我不能苟同,IT技術畢竟主導的是美利堅,學好英語、多看英文資料才是王道。
不過看樣子Unity的官方文件是會第一個本地化的,我最近也有文章在做翻譯工作,主要提高自己的英語閱讀水平和了解Unity各方面的細節,即使Unity官方文件出了,我還是會做下去。