Unity3D熱更新全書-指令碼(二) 兩級分化

瘋光無線發表於2014-08-02

上篇明確了我們探討的指令碼是什麼:是寫在文字檔案裡面的程式碼,可以作為資源載入,取得字串再執行。

可是為什麼世界上會有那麼多的指令碼?而其使用方法完全看起來不一樣呢?這是因為每種指令碼都有自己的定位,在不同的複雜度指令碼將表現出完全不同的樣貌,我們來看一下。

我們把指令碼與程式的結合方式劃分成五種,以複雜度排序說明。

C#Light是定位複雜度較低的指令碼,C#Evil是定位複雜度較高的指令碼,他們就在指令碼定位的兩級,可是有相當複用部分的程式碼,所以他們被合併成一個專案,你可以從GitHub上取得他們的原始碼。

程式碼獲取及文中示例的位置,在文後說明。

簡言之,指令碼可以兩級分化成兩種:

程式呼叫指令碼,指令碼為程式提供靈活性

指令碼呼叫程式,程式為指令碼提供擴充套件性

究竟是極左還是極右,怎麼使用,是你的自由。

我們用C#Light/Evil來說明各種指令碼結合方式。

 

複雜度一:計算

執行字串的核心函式應該是這樣的

int i = Eval(“1+2”);

imageimage

我們有一套例子,本文最後有如何取得例子的說明。

程式裡就可以通過執行字串來執行邏輯,字串的變更就可以得到邏輯的變更。

試想如果要做公式計算,他看起來應該是這樣

int i=Eval(“HP1+HP2*0.5);

這裡HP1,HP2怎麼來,就要把值傳給指令碼,讓指令碼計算

Script.SetValue(“HP1”,GetFromIni(“HP1”));

Script.SetValue(“HP2”,GetFromIni(“HP2”));

int i=Script.Eval(“HP1+HP2*0.5”);

image

複雜度二:包含邏輯分支和呼叫

當指令碼邏輯的複雜度到一個程度,直接嵌入字串就變得不可取了

我們希望在計算HP的同時,指令碼打點Log,就要讓指令碼可以呼叫函式,同時指令碼要知道今天星期幾,也得給他一個函式呼叫

這時候最好就把指令碼寫到一個單獨的文字檔案裡

Script1:

Debug.Log(“Today=”+Today());

if(Today()==Monday)

      return HP1+HP2;

if(Today()==SunDay)

     return HP1+HP2*2;

return HP1+HP2*0.5;

呼叫程式碼:

int i =Script.Eval(GetScriptFromFile(“Script1”));

image

image

 

複雜度三:函式與型別

當指令碼邏輯再複雜下去,僅靠表示式已經很難組織邏輯了,此時的指令碼就會引入函式甚至型別

Script1:

int Calc1()

{

   …

}

int Calc2()

{

   …

}

int Calc3()

{

   …

}

int GetHP()

{

    if(Today()==Monday)

    {

        return Calc1();

    }

    if(…)

    {

       ….

    }

    ….

}

呼叫程式碼:

Script.Build(GetScriptFromFile(“Script1”));

int i =Script.Eval(“GetHP();”);

這部分程式碼比較多,我們拆開來看

首先是指令碼檔案,這個看起來像程式碼一樣的東西就是我們的指令碼

image

然後我們把這個cs檔案當做文字載入進來作為指令碼,放在streamingasset目錄就可以

image

我們有兩種辦法來訪問Build好的指令碼,一種是合成一段字串,然後通過這組字串指令碼去執行

image

另一種是像反射那樣進行操作

image 


特別提醒:我們的建議是止步複雜度三

指令碼一旦跨越複雜度三進入複雜度四就會產生重心的完全反轉。

複雜度一二三是程式呼叫指令碼,指令碼為程式提供靈活性。

複雜度四五則變成了指令碼呼叫程式,程式為指令碼提供擴充套件性。


複雜度四:指令碼檔案進化成指令碼專案

再進一步複雜,指令碼就會進化為完全不同的東西

單個指令碼無法完成邏輯,指令碼和指令碼之間可以產生關聯

產生了專案的概念

Script1:

class ScriptClass1

{

      static void Run()

     {

          ScriptClass2 s2 =new ScriptClass2();

          s2.xxx

          …

          …

          …

     }

}

Script2:

class ScriptClass2

{

      …

      ….

      …

}

呼叫程式碼:

Script.BuildProject(“Scirpt1”,”Script2”)

Script.Run(“ScriptClass1.Run();”);

當指令碼變成了指令碼專案,再去觀察程式端的程式碼就沒什麼意義了

imageimage

我們的例子裡有用完全一致的程式端程式碼,僅僅切換了不同的指令碼,就完成了不同的功能。

按頂上的按鈕,直接載入兩個不同的指令碼專案進來執行

複雜度五:反客為主

當指令碼已經產生專案的概念,他已經可以脫離專用的程式宿主

像Python那樣用一個通用的Python.exe 啟動程式,變成一種擁有獨自執行能力的語言。

我們也提供一個這樣的例子,在這種情況下,程式設計師完全變成了指令碼編寫員和模組編寫員。

 

 

 

 

具體程式碼參考GitHub上的程式碼

https://github.com/lightszero/CSLightStudio

GITHUB原始碼中的Unity\ScriptHelloWorld中有四個場景

image

ScriptTest1_xx 分別對應複雜度一二三

ScriptTest2對應複雜度四

GITHUB原始碼中的Unity\ScriptLoader對應複雜度五,這個會在以後另外的文章中介紹

相關文章