Cocos 插件教程:編寫帶擴(kuò)展屬性插件的經(jīng)驗(yàn)分享
這兩天用cocos插件編寫了一個(gè)2d粒子控件。很明顯的感受是官方文檔不是很完善,那篇超級(jí)長的說明脈絡(luò)也不是很清晰,以至于我在此期間掉了不少坑走了不少彎路,不過這次cocos放出來的插件系統(tǒng)還是很靈活很強(qiáng)大的,從編輯到最終輸出都可以由我們自定義實(shí)現(xiàn)。這篇教程就來分享下我這兩天做擴(kuò)展屬性過程中總結(jié)的經(jīng)驗(yàn),探討在插件的編寫過程中的一些技巧,幫助下后來者。
一、如何開始?
可能大家之前看過這篇《Cocos Studio 擴(kuò)展說明》(下稱《說明》):
http://cn.cocos2d-x.org/tutorial/show?id=2650
這說明篇幅之大之長,估計(jì)嚇退了不少小伙伴。鼓起勇氣讀下去的估計(jì)半路上也睡倒了一片。(我就看到睡著了幾次,信息量實(shí)在太大了,催眠神器啊有木有。。。)
實(shí)際插件的編寫并沒那么復(fù)雜,直接修改官方提供的sample工程即可。
打開sample工程。(sample工程的路徑請(qǐng)看《說明》第3點(diǎn)“示例工程位置”)
可以看到里邊有這么多文件:
說明:
ü 其中DataModel、Templates和ViewModel是官方的一個(gè)Custom控件的示例,Lua文件夾下也有類似的三個(gè)文件夾,這個(gè)是帶文本sprite插件的源碼。
ü Editor是屬性區(qū)自定義控件的例子。
ü PublishExtend是自定義導(dǎo)出數(shù)據(jù)格式的例子。
ü AddinConfig是插件的配置文件,配置當(dāng)前插件所依賴的模塊,目前我們不需要改動(dòng)。
復(fù)制一份插件工程,保留我們希望使用的例子來作為模版,其他文件刪除。
我期望寫個(gè)粒子插件,不需要自定義Editor和導(dǎo)出數(shù)據(jù)格式,因而我只保留ExtensionModel和Lua兩個(gè)文件夾,并將“Lua”重命名為“Particle”,如下所示:
然后根據(jù)我們的需要對(duì)剩下的文件做一些修改:
1. LuaObject.addin.xml文件
修改為T4模版生成的類。
2. ViewModel下的CustomParticleObject.cs文件
這個(gè)文件需要改三處
a.這四個(gè)屬性主要用于編輯器顯示控件的一些信息。還有CustomParticleObject繼承的類型也需要根據(jù)自己的需要修改。(具體看《說明》中的“視圖模型”部分)
b.創(chuàng)建插件時(shí)的默認(rèn)名稱。
c.依賴的lua文件。即LuaScript文件夾下對(duì)應(yīng)本插件的Lua文件。
3.DataModel的CustomParticleObjectData.cs修改如下兩處:
4. Lua文件夾下的CustomParticleObject.tt模板文件,修改繼承的對(duì)象類型和ViewModel類的類名。(具體看《說明》“Lua 代碼生成模板”部分)
OK,改完這些,我們就配置完一個(gè)插件工程了。接下來我們還需要在lua中完成對(duì)引擎的擴(kuò)展,然后在編輯器中調(diào)用lua的接口。
PS:2.2.1升級(jí)至2.2.5之后,需要相應(yīng)地升級(jí)插件工程,具體可看新版本示例工程中Addins/Addins.Sample/Lua/修改記錄.txt
二、 編寫對(duì)應(yīng)的Lua文件
這一步主要是將我們的接口準(zhǔn)備好,給上邊配置的C#工程調(diào)用。
首先是必須做的四件事:
1.在文件的***返回一個(gè)table給插件工程,此后插件工程會(huì)在這個(gè)table上找需要的接口。這里我們稱這個(gè)table為“container”
2.為“container”添加CreateCustomNode的工廠函數(shù),創(chuàng)建一個(gè)我們擴(kuò)展的Cocos2d-x對(duì)象并返回。
3.為“container”添加一個(gè)GetBaseType函數(shù),返回我們插件的基礎(chǔ)類型。(之后我們的插件也會(huì)有這個(gè)基礎(chǔ)類型的編輯接口。)
4.把編寫出來的文件放到cocos文檔路徑的Addins/LuaScript下
然后在1所述的table上添加一些屬性接口來跟插件工程進(jìn)行數(shù)據(jù)交換,可交換的數(shù)據(jù)只能是如下這些數(shù)據(jù)類型,且一次只能交換一個(gè)數(shù)據(jù):
Bool
Int
String
Double
Float
Color
ResourceData
PS:lua下沒有區(qū)分Float、Double和Int,這些都用double來承載。
技巧:
1.插件工程在table上查找字段的方式不是用rawget方式,因此元表還是可用的,我們可以給table設(shè)置__index元表,重定向到我們的所擴(kuò)展的2d-x對(duì)象,某些我們所擴(kuò)展的對(duì)象已經(jīng)有的簡單接口用元表定位即可,不需要在table中再寫一次,減少一點(diǎn)工作量。
2.如果這個(gè)lua文件出錯(cuò)了,cocos不會(huì)給什么有用的調(diào)試信息。我們先在一個(gè)2d-lua工程里邊調(diào)試,直到所有接口都正常工作后再放到cocos中,這樣能節(jié)約不少時(shí)間。
3.這個(gè)文件跟最終導(dǎo)出的數(shù)據(jù)不一定有關(guān)聯(lián)。
三、 在插件工程中添加與lua層交換數(shù)據(jù)的接口
主要是給視圖模型(ViewModel文件夾下那個(gè)對(duì)象)編寫一些property,每編寫一個(gè)property編輯器就會(huì)在屬性區(qū)生成一個(gè)屬性控件。然后就可以用這些屬性控件來進(jìn)行可視化編輯。
與lua的通訊需要通過LuaValueConverter來調(diào)用Lua層的接口,進(jìn)行數(shù)據(jù)交換。
一個(gè)基本的property大概是這樣的:
[UndoPropertyAttribute]
[DisplayName("TangentialAccel")]
[Category("Group_Feature")]
[PropertyOrder(-99)]
[Browsable(true)]
public float TangentialAccel
{
get
{
return luaValueConverter.GetFloatValue("getTangentialAccel");
}
set
{
luaValueConverter.SetFloatValue("setTangentialAccel",value);
this.RaisePropertyChanged(() => this.TangentialAccel);
}
}
首先是幾個(gè)用中括號(hào)包著的attribute、當(dāng)前property的聲明然后是getter、setter定義。Attribute值的作用可以看看《說明》的“屬性區(qū)擴(kuò)展”一節(jié)。
其次還有setValue函數(shù)。這個(gè)函數(shù)在進(jìn)行克隆操作時(shí)發(fā)揮作用。將上述寫的property賦值給傳進(jìn)來的cObject對(duì)象相對(duì)應(yīng)的property即可。
技巧:
1.如果有比較多的屬性的話,可以先寫同一類型的擴(kuò)展屬性,調(diào)試到可用后復(fù)制黏貼,修改名字。
2.可以用Cocos Studio.Basic.LogConfig.Output.Info(String )在C#插件工程中輸出錯(cuò)誤信息。
3.調(diào)試時(shí)使用VS的“調(diào)試”-“附加到進(jìn)程”,附加到Cocos Studio主進(jìn)程進(jìn)行調(diào)試,C#代碼出錯(cuò)時(shí),VS會(huì)幫你指出出錯(cuò)的位置并且有詳細(xì)的調(diào)試信息。所有導(dǎo)致崩潰的錯(cuò)誤一般都能夠定位到。
4.目前l(fā)ua下沒有輸出錯(cuò)誤信息的接口,少量的調(diào)試信息可以用一個(gè)text控件放在創(chuàng)建的節(jié)點(diǎn)上做輸出。Lua下socket和io模塊還能夠使用,我們可以利用這兩個(gè)模塊來輸出調(diào)試信息,我使用的是socket,大家可以參考下我的源碼。cocos的研發(fā)同學(xué)表示會(huì)盡快提供log接口,到時(shí)就沒那么麻煩了。
四、 編輯DataModel
即CustomParticleObjectData.cs文件,以property的方式聲明下各個(gè)需要被保存到csd文件的性質(zhì),前面寫上[ItemProperty] [JsonProperty]。這樣這些數(shù)據(jù)就會(huì)被保存到csd文件當(dāng)中了,我們關(guān)掉編輯器再次打開,編輯過的數(shù)據(jù)就不會(huì)丟失了。生成T4模板的時(shí)候,模板里邊引用的值也是從這里來的。
注意顏色類型的性質(zhì)要用ColorData聲明(是的我被坑過)。這里可能出錯(cuò)的點(diǎn)是數(shù)據(jù)類型寫錯(cuò),現(xiàn)象是不能保存也不能導(dǎo)出。
五、 代碼生成模板
即Lua文件夾下的CustomParticleObject.tt模板文件。功能是將編輯器編輯出來的值按特定模板輸出出來。
技巧:
如果你看過我的lua文件和T4模板的話,你會(huì)發(fā)現(xiàn)二者之間毫無關(guān)聯(lián)。我的lua文件中的CreateCustomNode是創(chuàng)建了一個(gè)node對(duì)象然后再建一個(gè)particle對(duì)象做為node的子對(duì)象。這樣做的目的是為了能夠?qū)崿F(xiàn)更換粒子模板的效果(更換粒子模板需要重新生成粒子對(duì)象)。
其實(shí)T4就是根據(jù)模板將值填寫到字符串中,最終保存到文件里,愿意的話,生成C++代碼都沒問題。