我這里說的數據驅動,不是指某種框架,某種結構,或者某種編碼方式。 我要說的,是一種開發方式。
大家都知道,U3D中,我們可以為某個對象編寫一個腳本,然后將這個腳本掛在對象上,那這個對象就擁有了相應的能力。 但,由于腳本的威力是無窮的,它不僅可以操作這個對象本身,它同時還能改變整個世界。而U3D這種十分方便的開發模式,和你在FLASH CS中新建一個MovieClip,然后在它的時間軸上寫代碼如出一轍。 這種代碼驅動的方式,在某些場合是非常有用的。
比如。 怪物AI,狀態機,一些特殊的效果等(比如,攝相機振動)。
也就是說,如果我們想要讓自己的代碼很好地管理,那第一步,就是要限制代碼與對象的關系。 世界中的任何單體對象,都不應該擁有改變世界(游戲邏輯)的能力。它唯一能做的,就是操作它自己,同時,如果遇上了自己能力以外的事情,必須要向管理器報告。
所以,為了實現數據驅動,我們的游戲大概有以下幾種東西。
1、一個邏輯管理器,它決定了整個世界是如何運轉,不同對象之間如何交互
2、事件管理器,它負責接收來自各個對象的報靠,比如(啊,有人踩到我了;咦,這是一個傳送點耶;哎喲,你為什么點我。) 事件管理器起到事件隊列緩存的作用,同時,游戲邏輯應該定時處理這些事件。 當然,這個事件管理器,也是邏輯管理器的一個小弟,如果邏輯管理器覺得不怕麻煩,也可以親自操刀,負責事件收集。
3、若干對象相關的腳本,用于決定對象能力。 這些腳本不做別的,只做它們自己目標對象相關的事情。 比如,控制一個對象的動畫切換,檢查敵人是否進入攻擊范圍等等。 這些腳本,是做為腳本的一種能力掛上去的。當相應事件觸發時,他們會將事件通知給事件管理器。 理論上,我們是可以完全避免這樣做的, 就像早期的引擎中,對象只是資源,邏輯代碼用來操作這些資源。 但是,既然U3D提供了如此便利的東西,我們為何不用呢。 因為有許多事件的檢測,U3D已經為我們做好了,并且,也只有掛接在此對象上的腳本,才能夠監聽到這些事件。 比如OnTriggerEnter
當我們把代碼限制在一定范圍后,接下來的事情,就是限制場景樹(Hierarchy)中對象的使用。
U3D很強大,你可以通過對象關系、組件,參數調節,快速地構建出一個對象。 這一步,是必須的。 但我們還是要限制一下, 我們不允許非Prefab的對象在場景樹中出現,同時,Prefab除了Transform以外,不能被更改。(后面會說為什么,以及如何面對確實要更改的情況)。
接下來,我們來解決U3D中,一個操蛋的SVN沖突問題。 U3D的SCENE是基于二進制存儲的,不管你怎么整,怎么避免,都會有沖突,并且沖突無法合并。 那,這事兒太簡單了,我們不用它的SCENE文件就可以了。
需要做下面幾件事
一、新增菜單 打開場景,保存場景
二、當我們保存場景的時候,遍歷場景中的對象,將它們的transform,name,prefab,parentname存下來。輸出到文本文件中,記住,這一定要是文本文件,不然,照樣沖突。
三、如果只有一個文件,那沖突還是在所難免的,因此,我們需要把場景保存的時候,分割為多個文件。 如何分割呢, 我們需要提供一個配置文件,這個配置文件負責提供一個唯一的名字,以及對象ID段。 對象ID段的目的,這個對象ID,先前沒有提過,但作為一個場景中的對象來說,如果沒有ID,那將無法做到對它進行準確定位。 但,大家是工作在不同的機器上的,如果使這個ID唯一呢。 連接一個服務器? 那太坑爹了。 所以,我們可以把ID分段,項目組中,每個人擁有一個不相互沖突的ID段,和一個名字(可以是名字的拼音+后綴:如果有沖突的情況)。 當我們在編輯器中,把一個prefab拖入hierarchy的時候,修改這個對象的名字 ID_PrefabName_UserName 這樣,這個對象在場景中就有了唯一的名字。 當我們保存的時候,我們根據USERNAME,將場景保存到不同的子文件劃分中。
四、這樣一來,我們的U3D場景就不需要保存了。 那我們如何做到點PLAY就即時運行查看效果呢。 這里有一個小小的技巧性方案。 在我們的編輯場景中,新建一個GameObject,在它上面掛上一個腳本,這個腳本什么事都不做,直接start的時候,就LoadLevel("game"). (這里,假設我們的游戲場景是game,game是一個新建好的場景,且加入到了當前項目的場景列表中的。 這個game其實也只有一個GameObject,它負責啟動游戲。 加載我們先前輸出的場景文件).
還有一個細節要處理,由于我們的game場景只有一個,那我們編輯許多個場景,要如何查看呢。 那我們可以使用一個靜態變量來存儲當前編輯的場景,這樣game在加載的時候,就知道應該加載哪個場景的文件了。
五、為了使我們的開發更佳清析,在新建項目的時候,我們就新建兩個Scene 一個叫Editor,一個叫Game。 大家都在Editor里面工作。 最后發布的時候,只發布Game.
六、SVN的提交, Editor和Game是一開始就新建好了的,直接在SVN上把它鎖掉,禁止提交。 其余的文件,都是可以提交的。
這樣,我們的U3D,就和自家引擎一樣了。
在實施的過程中,我也遇上了一些問題。
一、保存場景的時候,取得所有的對象, 為了保證得到完整的場景樹TOP結構,我有一個SceneRoot的空GameObject,所有的東西,都掛在這個下面。 當輸出的時候,我直接從SceneRoot開始遍歷,從而拿到了完整的parent,child關系。
二、監聽對象改變的事件,我目前,只能在EditorWindow的OnHierarchyChange里面來做,但這樣做有個不好的,就是這個EidtorWindow需要保持顯示,如果不小心關了,就失效了(不知道哪位兄弟有更好的辦法)
三、由于這套東西,沒有使用U3D的場景保存功能,所以,CTRL+S是無效的。 不過,CTRL+S可以讓你的東西保存到Editor.unity3d里面,雖然不可以提交,但不會導致你的東西丟失。
四、使用的過程中,也出現了一些大大小小的問題。
五、目前是強制讓Prefab的其它屬性不可修改,如果有變動的,就新建一個Prefab. 或許還有更好的辦法.
如果有喜歡這個東西的朋友,可以一起來完善。
文章列表