在遊戲中儲存遊戲進度時一般會儲存哪些信息?以什麼方式存儲?

嗯,打個比方來說。儲存的時候是直接儲存字元串然後再讀取的時候解析之;或者自己設計一套編碼方式,按位存儲;又或者直接把內存中的對象存下來。一般有哪些方式,會做哪些方面的考慮與優化?


@何騫 肯定沒有做過遊戲行業的業務,不可能截屏等做法的,以及說大型網路遊戲的數據龐雜,更加說明對這方面的業務一竅不通兄弟

遊戲都會有地圖數據的,也即你所在的地圖位置坐標等數據,會存儲在資料庫中的。

遊戲行業對於玩家的裝備等機密信息,多數採用BLOB數據類型進行存儲,或者自己加密之後的數據存儲在TEXT類型欄位中,都是為增加公司內部人士犯罪成本而一直堅持的傳統做法。若是一位DBA想做類似的事情,這些都是沒有任何價值的,所以部分公司開始改變傳統做法,每個物品存成一條記錄,但是大部分公司的大型網路遊戲或Web Game依然採用以前的做法,另外一個原因即是,開發人員對這個模式非常熟悉,而且資料庫負載不是問題,根本就沒啥大壓力。

SNS Game也即社交遊戲行業不一樣,不是那種分區分服的做法,而且玩家人數眾多,像社交遊戲火熱時,安裝用戶量1000W級別是正常的行為,為此不得不考慮性能和成本等因素,所以是改成單獨存儲成一行數字編號的模式,而不是以前使用的JSON串格式,當然部分公司也依然這麼做!


單機遊戲的存檔設計,要考慮到設備性能,和遊戲需要。

設備性能,主要考慮存檔設備的容量,和讀寫速度。
遊戲需求則多種多樣,難以細說。

遊戲邏輯一般是用狀態機模型運轉的,我們需要儲存的信息主要是狀態。
我們可以把所有的狀態對象都設計成繼承自同一內存池存儲對象,這樣我們存檔時只需要把內存池中的內存塊做持久化(處理好地址偏移就能很方便的恢複數據)即可。
當然,我們也可以通過遍歷狀態機的數據結構,把狀態機里的狀態一一記錄到存檔設備上。
內存快照的方式有些類似內存池持久化,不過以前有些實現沒有太按照面向對象來做。模擬器存快照最方便~

我覺得關鍵問題還是哪些數據要存檔,數據如何組織(跟遊戲邏輯有很深的關係)。如果數據太離散,那麼肯定是用內存池持久化的方式更方便些。

現今的設備都十分強大,多數情況下,無需考慮性能問題,如何方便編碼如何設計。加密的功能,其實意義不大。單機遊戲,玩家要作弊的話就讓他/她作弊好了。無傷大雅。


從網遊的情況來看,先定義好一個包含所有玩家信息的資料庫表結構,用一張表存儲玩家的所有數據(角色經驗,等級,技能,背包物品,地圖,角色形象等)即可,載入只需要讀取數據,然後具化(或者寫入)到遊戲系統中。
遊戲系統是獨立於玩家數據存在的,以固定資源文件形式存在,當輸入一定的玩家數據後,就可以生成對應的遊戲內容。


根據遊戲類型和具體的設計要求,在存檔的過程所要考慮存儲的信息也有所不同。通常情況下引擎會讀取內存中的關鍵參數(如LV/HP/MP/EXP等),將其序列化以後存儲,讀取的時候再反序列化載入。

早期的不少遊戲(比如FC上的勇者斗惡龍,天使之翼和聖鬥士黃金傳說)都採取了密碼存儲的方式,原因是那個年代的遊戲數據量較少,所要求的存儲空間也十分有限(往往不超過512位元組),使用長密碼記錄完全可以保存當時的存儲狀態。
密碼存儲的方式在現在也偶爾可以見到,最簡單的應該當屬選關密碼,畢竟可以不涉及玩家當時的狀態。從原理上說,只要哈希表能大到把所有對應的內容都設置好,那麼用密碼存儲是完全可行的做法。

現代大型遊戲的數據量相當龐雜,基本不大可能會直接存儲內存狀態,而存儲的過程中也更多要考慮到數據加密的問題。此外,為了讓存檔數據對玩家更清晰可辨,存檔數據中有可能會包含當前遊戲的環境的截屏或是讀取遊戲中事先整合好的場景預覽圖片。

末了,關於存檔系統的設計,Game Developer Magazine上曾經刊登過這樣一篇文章,也可以在gamasutra上找到正文,Saving the Day: Save Systems in Games http://www.gamasutra.com/view/feature/1935/saving_the_day_save_systems_in_.php?page=1
Stackoverflow上也有相關的問答可以參考,比如http://gamedev.stackexchange.com/questions/2617/game-state-saving-loading


以前玩過一個魔獸爭霸的RPG,那是我玩過的第一個能記錄的RPG地圖。原理是生成一個128位的密碼,自己複製粘貼到記事本上,下次進入遊戲的時候輸入-load 密碼就可以了。

我們曾經試過改動這個密碼,然後觀察載入的結果有何不同;在早期的地圖版本里,這個密碼基本上等於是一個明文存儲的數據包,包括等級,裝備代碼,任務進度等。後來作者用了某種方法加密,因為當時水平就限,就沒有深究原理。現在想起來,大部分遊戲可能都是這麼存儲的。

這種加密方式用的挺廣泛的,包括網遊點卡的生成,將軍令,軟體序列號生成什麼的。可以參考下密碼學方面的人士有什麼意見。

PS:以一個老玩家身份補充一點:遊戲中的存儲,大概分3類,第一種,你可以理解成街機遊戲的存儲,它存儲的是一個瞬間的狀態,比如你玩街機模擬器,按下F8存儲的是那一瞬間的遊戲狀態,包括各種遊戲資源,角色的位置,屏幕上飛行的道具以及他們飛行的速度方向等等;第二種是存檔點存儲,例如生化危機的打字機+色帶模式,存儲的基本上是存儲點+物品;第三類是暗黑破壞神II那類的存儲,每次重新載入的時候其實會給你送回存檔點,和第二類差不多。

第一次在這裡回答問題,希望對你有幫助。


我簡單的看過仙劍4的save文件 ,仙劍4的save文件貌似比較簡單,它存儲的信息包括主角的屬性(運、速、攻擊力 防禦力 等)、主角的當前的精氣神以及最大值、主角的裝備情況、當前的金錢數目、累計遊戲時間等、主角存檔時候所在的坐標。這些信息都是明文存放在dat文件中的。


不同的遊戲存儲方法不同,也根據玩家的具體需要來定。
1.基本的都只是存儲玩家屬性的數據結構,然後恢復時載入。
2.存儲遊戲具體環節的屬性,形成簡單的文件比如xml,然後序列化。
3.費時費力的就是存儲快照了,像虛擬機一樣~


在某些情況下,玩家的世界信息和輸入一般也會被快照下來,即向網路發送自己的狀態時,同時也寫入本地,用於回放和矯正


Xml


這麼說吧,有一張表叫player,裡邊有這個玩家的所有需要存儲的信息。比如這個人下線的時候所在的地圖坐標。這個人的裝備信息,有可能是這樣存的:首先存一個數量,然後依次寫入每件裝備需要存儲的信息,比如這個裝備的id等等。讀入的時候就按寫入的順序依次讀一個數量,然後一個for循環依次讀每個裝備信息就OK了。其他的模塊任務信息啊技能信息啊同理,每隔膜塊都有自己的存儲方式和讀入方式。也有可能每個模塊都作為一張表,但是原理沒變。社交遊戲和單機遊戲沒做過,不作解釋。


我怎麼覺得,就跟編輯一個word文檔,中途保存進度是一個道理呢。
說白了,就是model 和 view 的關係。遊戲裡面看到的那些畫面,只是表現形式而已,遊戲的進度數據用遊戲模型定義好了,直接保存就行了。至於保存的格式問題,xml可以保存任意複雜的數據,但是效率很低。一般遊戲都會定義獨有的格式,每個數據位都可以有它特定的含義。


早期遊戲有直接文本的,也有文本加密的,也有微型資料庫的。
還有請說明遊戲的類型,這個比後面那個問題還重要。


其實你編碼的時候,和遊戲狀態有關的Model單獨寫出來。然後就是序列化這個對象。
如果是用 C#/Java ,用自身的 Serialization 機制就可以。其中自己也可以定製一些 readObject、transient 的東西。至於存儲是 XML、還是二進位,取決於 Serializer 。
如果是用 C++ ,就要手動實現一下這個方法,相對來說複雜一些。

比如打磚塊遊戲。Model包括:

用戶:多少條命、積分、模式 …
小球:位置、速度、方向、屬性 …
粘板:位置、屬性 …
磚塊:坐標、屬性 …

此外,紋理、模型之類的對象,不要交給 Model,由 View 層負責。


不同遊戲不一樣吧,簡單的的比如小鳥,就是直接用lua存。
複雜點的個人認為把內存結構序列化就OK了。


我記得我學習什麼東西的時候,偶然間掃過一個遊戲存儲設計。它好像主要是用的xml存儲,信息存的是人物信息。比如級別,位置什麼的。


難道你沒用過存檔修改器?


一句話:
遊戲世界的快照(重建世界需要的狀態數據)。


推薦閱讀:

如何把握中大型軟體開發流程?
純C語言的工作有前(錢)景嗎?
有哪些能規劃旅行路線的 App?
一個人如何開發一款 App?
作為計算機專業學生,最應該學習的課程前五位是什麼?

TAG:遊戲 | 軟體開發 | 遊戲開發 | 遊戲編程 | 數據存儲技術 |