C# Unity遊戲開發——Excel中的數據是如何到遊戲中的 (四)2018.4.3更新

 本帖是延續的: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,空間佔用少,速度快。或者本身寫。

相關文章
相關標籤/搜索