該怎麼樣用C++來實現類Unity3d的AddComponent
阿新 • • 發佈:2019-01-26
Unity3d 越來越完善,朝著它學習的人也越來越多。一是因為Unity3d是一整套開發工具,使用起來簡單快捷。二是 Mono C#的快速開發上手簡單。
在Unity編輯器中,新增一個GameObject , 然後把一個繼承自MonoBehavior的指令碼拖到GameObject上,即可對GameObject進行操作。或者在程式碼中new 一個GameObject,然後用AddComponet 掛載一個指令碼到GameObject上。
AddComponet 這個函式,可以通過傳遞 String 來例項化一個類。該如何用C++來實現類似的功能呢?
首先介紹一下Unity 的一些原理:
(1) 我們編寫一個類繼承自MonoBehavior ,然後新增 Start 、Update 這些函式。但是這些函式其實是私有的,並不是從MonoBehavior中繼承而來,那這幾個函式是在哪裡呼叫的?
Unity中通過反射來判斷一個類中有沒有對應的函式,引自知乎中的一個回答:
Unity的確是通過反射來呼叫指令碼的方法的,並且這一過程會在執行時不停對所有MonoBehaviour遍歷進行。 Unity之所以統一地使用這一套固定的函式命名方案,便於明確地劃出了每個函式需要做些什麼。 這樣做的目的我猜測是有利用保留指令碼的靈活性。 這種做法被慣稱為“事件機制”,一旦某個指令碼被執行完成之後,它的控制權會重新回到排程管理處,可以輕鬆地再去執行下一個, 並且也能在執行時通過反射方式讓其它指令碼使用Component.SendMessage進行呼叫。 如果採用了抽象方式讓子類去實現這樣的方法,那麼對於Unity本身的物件管理是沒有任何好處的,並且對於擁有多個指令碼元件的物件來說,維護成本不但增加了, 還可能讓指令碼之間的管理變得混亂。 使用反射也許會丟失一些效能,但卻能讓每個不同的MonoBehaviour之間看起來都是獨立的,只需要在它提供的幾個內建方法中關注自己的邏輯就可以了。
那 C++ 呢?C++判斷類是否有某個函式不好弄,所以還是採用繼承的方式來簡單實現 AddComponet 。
這種方法的關鍵就是如何使用類名來建立類例項。
其中一種方式就是 , 讓通過類名例項化的類 繼承自 基類 ,然後通過靜態函式在程式最開始執行的時候,向基類註冊,然後在呼叫 AddComponet 的時候,通過基類的函式在最開始註冊的子類中尋找是否有對應名字的子類,如果有的話就例項化子類。
最終簡單實現Unity3d中的AddComponet 函式。
int main() { GameObject* obj=new GameObject("Cube"); NewMonoBehaviour* newmono=(NewMonoBehaviour*)obj->AddComponent("NewMonoBehaviour"); MyMonoBehaviour* mymono=(MyMonoBehaviour*)obj->AddComponent("MyMonoBehaviour"); for (int i=0;i<obj->m_componentVec.size();i++) { std::pair<string,Component*> compmap=obj->m_componentVec[i]; MonoBehaviour* mono=(MonoBehaviour*)compmap.second; mono->Awake(); } system("pause"); return 0; }
程式碼下載:
http://pan.baidu.com/s/1i3rcYPZ