序列化在遊戲開發中的運用

2021-08-22 17:57:58 字數 1755 閱讀 2996

在伺服器內部,大部分資料都是以物件的形式儲存的,那麼如果可以直接發乙個物件傳送給客戶端或是其他程序來完成通訊,既會非常直觀方便,也不同意出現不一致等問題。

序列化和反序列化直觀上就完成了物件->位元組流以及位元組流->物件的轉化過程。

一般情況下,以下幾種情況下,需要用到序列化

跨裝置/跨程序,比如伺服器和客戶端之間的通訊,伺服器組內部的通訊

伺服器和儲存程序的通訊,比如把乙個物件儲存到redis或者mysql

伺服器把資料向外以api介面形式展示給外部,比如通過webapi開放物件資料的查詢

效能(速度和空間),一般主流的演算法速度正比於空間,所以不單獨討論兩個指標。很多演算法(比如protocolbuf)會對資料進行一定的壓縮,或通過編碼的方式儲存來降低空間的開銷。

序列化後的內容是否支援可見文字編碼,文字儲存的好處是,除錯非常容易,特別是在開發期間,可以很方便的定位到問題。

是否支援版本公升級(比如增加字段,重新命名字段)。兩端如果處於不同的版本,如果支援版本公升級的演算法,就具有一定的容錯性。但這個功能的實現往往需要通過空間上的額外資訊來支援。回過來提一下,一般我們並不需要強制限定通訊雙方的協議版本/物件版本完全一致(如果真需要這麼做完全可以參考.net自帶的序列化方法,基於強型別版本號的一致性比對)。

效能文字編碼

版本公升級

跨裝置/跨程序高按需

儲存低√api介面低√

√這裡的第三點api介面方式,一般較多用開源的方案(json),這麼做比較有利於遊戲開放商和運營平台間的協作。而前兩種使用也可以選擇開源的protocolbuf類庫,下面我就簡單講一下如果要自己實現前兩種方案有什麼注意做的。

舉例,我們需要序列化的物件定義如下

class testweapon

最簡單的方式就是,依次序列化/反序列化三個成員變數。而採用binarywriter的編碼方式可以讓序列化結果的熵最大化(不考慮壓縮等優化手段)。而這種做法,基本滿足了上文關於跨裝置/跨程序的需求(高效能,不支援版本公升級)。所以伺服器內部(一般伺服器內部程序都是在乙個序列化版本控制之下的),伺服器和客戶端同信(大部分遊戲,伺服器和客戶端也可以保證是處於乙個版本的)就可以採用這種序列化方式。

這時候,我們儲存的結果類似於

313|ak47|95

如果我們用上面這種序列化的方式,當在某個版本把物件序列化後存回db,一段時間後在需要把資料取出來,可能就會遇到無法反序列化的情況(可能在power前新加了乙個欄位level)。

所以我們需要一種方法,可以支援物件版本的公升級。乙個簡單的思路是,我們儲存時不僅僅儲存資料,同時還對欄位名進行儲存,類似於key-valuie儲存的方式。讀資料的時候,可以先讀取key,在把資料(value)儲存到key所對應的儲存位置上

。這時候,我們儲存的結果類似於(當然實際上是二進位制儲存的)

weaponid-313|weaponname-ak47|power-95

這就有乙個很明顯的缺點,欄位名重新命名了,序列化就會失敗,或者說欄位名很長的話,序列化效能就會比較差。

所以,我們希望可以優化欄位名的儲存效率

class testweapon

以此,我們引入了乙個attribute-storeindex。通過讀取欄位的特性值,我們最終儲存的資料直接和index掛鉤,而不是欄位名(當然就要求類內部的index不重複)。這時候,我們的儲存結果就變成了。

1-313|2-ak47|3-95

效率就非常接近於純value的序列化了。

遊戲配置序列化

遊戲中提供很多可供配置的設定,有利用適應多種不同的硬體配置,也有利於適應用不同玩家的操作習慣.如果每次進遊戲的話都要重設一次,這顯然就失去了配置的意義,不如用乙個適用範圍比較廣的預設值算了.所以,配置需要儲存.windows中就有眾多的的ini檔案,還有一些軟體會把資訊存入登錄檔.但是,當配置資訊較...

php中序列化和反序列化函式在快照中的使用

php中序列化和反序列化函式在快照中的使用 1.序列化函式 string serialize mixed value 2.反序列化函式 mixed unserialize string str 簡單例子 arr array array name 張三 age 18 array name 李四 age...

Python中的序列化和反序列化

python中的序列化和反序列化通常有兩種模組的使用 1 pickle模組 2 json模組 1 序列化 就是把不可傳輸的物件轉換為可儲存或可傳輸的過程 2 反序列化 就是把在磁碟,等介質中的資料轉換為物件 描述 對於大多數應用程式來講,dump 和load 函式的使用就是你使用pickle模組所需...