本帖是延續的:C# Unity游戲開發——Excel中的數據是如何到游戲中的 (三)
前言
最近項目不算太忙,終於有時間更新博客了。關於數據處理這個主題前面的(一)(二)(三)基本上算是一個完整的靜態數據處理方案了。
不過前幾篇發布的時候是2015年,比較早了,隨着這幾年技術不斷積累和進步,其實已經有更好的方案來處理數據了,不過對於前端存儲的那幾個M的數據,多點少點其實影響也不大。
但是也不能就這樣算了,畢竟技術的變化日新月異,還是要保持持續學習的心態。
雖然簡單但卻不易忽視
對於游戲中靜態數據的處理,單純的對於整個程序項目來說其實只是很小的一部分。寫個讀寫工具,打個包,壓個縮,加個密其實對於很
多程序來說也不是難事。但是,我又要說但是了。但是,根據博主的個人經驗來說,數據對於游戲的業務邏輯是非常底層的“邏輯”,對於
后期的開發起到了一個基礎的作用。主要體現在兩個方面:
1.業務邏輯角度的數據結構化。
這點很關鍵,策划想要把自己大腦里的游戲玩法用數據表示出來,而這個表示過程其實是需要程序配合的,因為不可能每個策划
都那么牛逼,然而現實情況也確實如此。因此,這部分要做的事就是,用數據抽象的思維把策划描述的游戲世界表示出來,最終
體現就是“表格”。這些數據,其實就是游戲業務邏輯的“骨架”,后續的開發都是圍繞着數據來做的,或者說被數據“支配”的。
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,空間占用少,速度快。或者自己寫。
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 http://www.cnblogs.com/fly-100/p/8707749.html
