(轉載)李劍英的CSLight入門指南結合NGUI熱更新

weixin_33850890發表於2015-12-17

Babybus-u3d技術交流-(轉載)李劍英的CSLight入門指南結合NGUI熱更新

李劍英的CSLight入門指南文件撰寫者:GraphicQQ: 1065147807
一. CSLIGHT 作者簡介
CSLight的作者是李劍英,一個有著美麗心靈的遊戲圈程式設計師,群中人稱李總,他的技術群是:【低端程式設計高階研究–223823428】。
二. CSLIGHT 為何而生
CSLight 最初出現的目的是為了解決Unity3D在IOS平臺上的程式碼熱更新的問題。 因為IOS平臺上的程式碼熱更新問題無法通過Mono Reflection機制來解決,故而只能引入指令碼。目前市面上的U3D指令碼解決方案不多,被聽說過的大致有三種: CSLight UniLua SSharp,三者中CSLight的優點較為出眾:1. 指令碼執行效能最佳, 這個是因為李總的CSLight指令碼直譯器實現的非常輕量, 不刻意追求語言基礎設施的完善性,在保證充分可用性的前提下,完全的走實用主義道路,故而執行效能最佳。2. 指令碼語法相容U3D專案開發中的標配C# 語言的大多數常用語法,藉助李總的CSLightFramework,可以在原始檔級別上一定程度的做到 原生C# 和 指令碼C# 檔案的無縫切換。3. CSLight有商業嚴肅專案的考驗經歷。
故,CSLight是Unity3D指令碼解決方案的充分可行之選。
三. CSLIGHT 框架說明CSLight從巨集觀上來看,只有兩個部分,一個是CSLight直譯器,另一個是CSLight框架。對於剛接觸CSLight的新人來說,CSLight最重要的是CSLight框架→ CSLightFramework,這個輕量級的框架設計的很漂亮, 這裡先大致掃一眼該框架的結構和類圖:

[
(轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 1

這個框架簡潔優雅的實現瞭如下的兩個目的:1. 開發者可以快速的上手開發,通過框架的封裝,使得開發者不需要關心底層直譯器的機制。2. 藉助框架,一個C# 指令碼檔案,可以選擇以【原生模式(Mono虛擬機器)】 或 【CSLight指令碼模式(CSLight直譯器)】這兩種不同的執行模式來執行。那麼為何需要兩種執行模式呢?這是為了方便在IDE中除錯指令碼程式碼,因為只有在【原生模式】下執行才能借用IDE的斷點除錯等功能。可等程式碼穩定之後再切換到【CSLight指令碼模式】。參照上面的類結構圖:【原生模式的執行】是通過CodeFile_Debug類 的包裝來達成的,其藉助了反射機制來做到本地化執行。【CSLight指令碼模式的執行】是通過 CodeFile_CLScript類 的包裝來達成的,其呼叫了CSLight底層直譯器的介面來做到解釋型的執行。
嗯,是時候需要一個典型的HelloWorld的例子,來進一步的理解這個框架了,這裡就用經常有人問到的【CSLight如何與NGUI互動】來作為例子。嗯,One more thing,在進入入門示例章節之前,有個非常重要的問題必須要先提一下,就是【指令碼】與【宿主環境】如何互動的問題!熟悉Lua的朋友會知道,Lua是通過【設定Lua虛擬機器堆疊】的這種方式來和C/C++的【宿主環境】進行互動的。那CSLight的【指令碼】是如何與Unity3D原生C#的【宿主環境】進行互動的呢?嗯,答案是:在宿主環境中的自定義介面!看一下CSLightFramework框架中 ICodeFile 的定義如下:

[
(轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 2

其中的泛型T 就是【指令碼】與【宿主環境】之間互動的關鍵所在,也正是上文強調過的【在宿主環境中的自定義介面】!下面開始進行【CSLight如何與NGUI進行互動】的例項演示。
四. CSLIGHT 入門示例 — CSLIGHT 如何與 NGUI 進行互動
一個有意義的,同時又簡潔的示例不太好找。這裡隨便選的一個示例是:【如何用CSLight指令碼來控制NGUI中一個元素的縮放。】雖然這個例子本身沒有實際的意義,但通過這個例子搞懂框架的原理後,就可以很容易的做出一大堆有意義的事情來。

  1. 新建一個Unity3D工程和場景,並把CSLight和CSLightFramework 這兩份工程程式碼拷貝進去。2. 新建一個NGUI_Root,並在 預設的Panel 節點下新建一個UISprite,然後隨便弄個圖片顯示。此時的大概情形如下所示:

    [
    (轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 3
  2. 在專案中新建一個程式碼介面檔案,作為【在宿主環境中的自定義介面】,大致如下面所示的樣子:[
    (轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 4

其中第一個介面:SetNGUIElementScale(float scale); 設定NGUI某個元素的縮放,這個就沒什麼好說的了,屆時CSLight指令碼會呼叫這個宿主環境中的介面,傳入想要縮放的數值。其中第二個介面:IScript物件的getter方法,這個也沒什麼好說的,這個介面是框架約定必須要實現的,因為CSLight指令碼方法之間的互相呼叫需要用到這個。

  1. 回到Unity3D中,在NGUI預設生成的那個Panel 物件上繫結一個控制指令碼(繼承自MonoBehaviour),比如叫 TestController .cs,大體情形如下圖所示:(記得要給那個 UISprite 物件賦上引用)[
    (轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 5
  2. 通過繼承框架中的 ScriptMgr類來建立自己的指令碼管理器,程式碼大致如下圖所示:

    [
    (轉載)李劍英的CSLight入門指南結合NGUI熱更新 - 雨鬆MOMO程式研究院 - 6

    注意這一步需要繼承並實現 ICLS_Logger 的三個介面(Log, Log_Warn, Log_Error),因為在 ScriptMgr 指令碼管理器 例項化的時候,建構函式需要一個實現了ICLS_Logger 的物件作為引數。
  3. 開始編寫CSLight 真.指令碼檔案 :Script_Test .cs,如下圖所示,注意這個指令碼檔案要放到 Assets/StreamingAssets 目錄中,以方便後面使用WWW來載入,用於模擬熱更新時的遠端指令碼載入機制。[[圖片上傳中。。。(7)]

這個 真.指令碼檔案 的寫法有幾處地方要特別注意:6.1 所有的方法必須是靜態方法,否則無法切換到【原生模式】來執行,也就無法用IDE來Debug了,這是框架內用反射模擬原生模式時的約定。6.2 必須有一個靜態方法名叫:_new,類似 int main() { } 。6.3 每個靜態方法之間不能直接互相呼叫,需要通過圖片中註釋的說明方法來呼叫.6.4 所有方法的第一個引數,必須是 【宿主環境中的介面】→ Interface_Test 物件.7. 最後一步: 在TestController .cs 中繼承並實現 【宿主環境中的介面】,然後載入上面的那個指令碼並執行。7.1 實現【宿主環境中的介面】→ Interface_Test,程式碼如下所示:[[圖片上傳中。。。(8)]
7.2 載入指令碼並執行,程式碼如下所示:[[圖片上傳中。。。(9)]
至此,這個例子就結束了。

相關文章