本帖是延續的:C# Unity遊戲開發——Excel中的數據是如何到遊戲中的 (三)html
前言前端
最近項目不算太忙,終於有時間更新博客了。關於數據處理這個主題前面的(一)(二)(三)基本上算是一個完整的靜態數據處理方案了。java
不過前幾篇發佈的時候是2015年,比較早了,隨着這幾年技術不斷積累和進步,其實已經有更好的方案來處理數據了,不過對於前端存儲的那幾個M的數據,多點少點其實影響也不大。git
可是也不能就這樣算了,畢竟技術的變化突飛猛進,仍是要保持持續學習的心態。github
雖然簡單但卻不易忽視數據結構
對於遊戲中靜態數據的處理,單純的對於整個程序項目來講其實只是很小的一部分。寫個讀寫工具,打個包,壓個縮,加個密其實對於很工具
多程序來講也不是難事。可是,我又要說可是了。可是,根據博主的我的經驗來講,數據對於遊戲的業務邏輯是很是底層的「邏輯」,對於學習
後期的開發起到了一個基礎的做用。主要體如今兩個方面:測試
1.業務邏輯角度的數據結構化。google
這點很關鍵,策劃想要把本身大腦裏的遊戲玩法用數據表示出來,而這個表示過程實際上是須要程序配合的,由於不可能每一個策劃
都那麼牛逼,然而現實狀況也確實如此。所以,這部分要作的事就是,用數據抽象的思惟把策劃描述的遊戲世界表示出來,最終
體現就是「表格」。這些數據,其實就是遊戲業務邏輯的「骨架」,後續的開發都是圍繞着數據來作的,或者說被數據「支配」的。
2.程序結構的設計。
第一條說過了,「後續的開發都是圍繞着數據來作的」,那麼這些數據的使用頻率必然會很高。那麼,問題來了,如何設計這部分的程序結構會使開發效率和運行效率最優?單純的建立一個類,把全部數據查詢的方法都放裏面?仍是根據第一條抽象出來的「實體類」來組織數據,而後對數據作一些預處理,例如遊戲運行先進行分類而後放到內存中等待使用?
顯然,後者更加高效,這也「靜態數據處理雖然簡單,可是也不容忽視」的理由。
最新的方案
前面也說了,技術是不斷在變化的,咱們也須要快速適應。以前的方案確實用了很長時間,也沒什麼問題。可是本身擼的代碼總有幾個疑問?這是最好的方案嗎?和最好的方案差距有多大?
帶着這幾個問題,在最近2年所作的項目中也對這方面作了一些工做:1,在最近的項目中使用了ScriptableObject的方式。2,開始了一個protobuf方式處理數據的開源項目。
提及來慚愧,其實結果影響並不算很大,下面把這部分總結一下。
方案一 : 使用Unity的ScriptableObject。
作法就是每一個表格生成的數據類都直接或者間接的繼承自ScriptableObject類,打包的時候直接把全部表數據都生成一個對應類型的.asset文件。而後建一個總的Map類來存放全部asset的引用,固然這個Map類也必須繼承自ScriptableObject,也生成對應的.asset文件。最終打包的時候,只打這個Map類的.asset文件,Unity會自動識別裏面的依賴關係,將全部數據打包進bundle。
實體類Hero
using UnityEngine; public class Hero : ScriptableObject { public string name; public string level; }
Map類
using UnityEngine; using System.Collections.Generic; public class Map : ScriptableObject { public List<Hero> heroList = new List<Hero>(); }
最終在使用的時候也很方便:
AssetBundle bundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/constance"); Map m_Constance = bundle.LoadAsset("constance") as Map;
這種方式對Unity3D很是友好,使用起來也很是方便,可是缺點也是有的,下面來總結一下:
優勢:
能夠和預製產生依賴,prefab若是依賴了asset打包的時候也會打進去,減小了查找操做。
能夠直接用Unity API操做asset。省去了一部分序列化反序列化代碼。
能夠直接用AssetBundle.LoadAsset() as Map;加載,省去了以前的反序列化代碼。
在Unty中選中asset能夠直接在Inpector中看到數據。
缺點:
生成asset的時候會有大量的文件操做,速度慢。
還有兩個指標就是運行速度和存儲空間。因爲影響不大,沒有作進一步測試。
存儲空間的話,我這裏有個參考:6個Excel文件佔用的pc上的磁盤空間是112k,最終打成AssetBundle是31k。
方案二 : 使用protobuf
這種作法主要是經過google提供的protobuf來序列化和反序列化數據,而且使用protoc生成目標語言的代碼。工做流程以下圖所示。
把作法分紅幾部分來講:
操做1,讀取excel數據描述信息,經過excel數據描述信息生成.proto文件。
操做2,使用protoc命令行生成本地代碼,也就是你製做工具使用的語言代碼。
操做3,建立本地代碼的類的實例。
操做4,讀取excel數據,而且將內容賦值給「操做3」建立的實例,最終使用protobuf API序列化。
操做5,生成目標平臺的代碼。
最終生成的二進制文件(.bytes)和目標代碼會和程序一同發佈,使用生成的目標代碼解析生成的二進制數據。
具體代碼就不貼出了,下面是本人對方案二開啓的一個開源項目,用的是java+netbean8.2,目前已經完成大部份內容。
有興趣的同窗能夠看一下。我會一直更新。
https://github.com/superbig/proto-packer
最後
若是你在遊戲開發的靜態數據處理方面還在猶豫,建議是:若是項目小但是試試ScriptableObject方式,應使用起來確實要方便一些。固然你也須要忍受數據導出時候的頻繁的IO操做(固然其實你也能夠開發一個增量導出的工具)。
若是項目大,數據不少仍是老老實實用protobuf,空間佔用少,速度快。或者本身寫。