數(shù)據(jù)持久化設(shè)計(jì)
很久沒(méi)有總結(jié)做過(guò)的東西了,今天來(lái)小結(jié)一下最近兩天做數(shù)據(jù)持久化的一些心得;所謂數(shù)據(jù)持久化簡(jiǎn)單來(lái)說(shuō),就是保存和加載。目前只做了切換場(chǎng)景時(shí)保存標(biāo)記為持久化對(duì)象的單位的狀態(tài),等重新切換回來(lái)時(shí),再加載;和退出游戲加載存檔的機(jī)制是一樣的。我選擇使用了二進(jìn)制存檔的方式,思路大致如下:
1、給游戲?qū)ο蟮幕愔屑右粋€(gè)變量和一個(gè)guid的字符串
這里的Const.emptyGuid是存儲(chǔ)的一個(gè)全局值,Guid.empty.ToString();
2、在基類或其派生類的面板工具中添加自動(dòng)生成Guid的邏輯
生成Guid的代碼也很簡(jiǎn)單
3、將ForceUpdateGuid設(shè)置成菜單功能,由于Guid無(wú)法被編輯,所以要做一個(gè)自動(dòng)全部重新生成的功能。(因?yàn)椴幌M鸊uid被手動(dòng)編輯,1來(lái)操作麻煩,2來(lái)防止誤觸,自動(dòng)創(chuàng)建更能保證他的唯一性;這個(gè)自動(dòng)創(chuàng)建最開(kāi)始是打算在Awake時(shí)執(zhí)行,但是后來(lái)還是打算做成菜單功能,擔(dān)心Awake創(chuàng)建會(huì)有問(wèn)題,具體啥問(wèn)題沒(méi)去想,總之自我感覺(jué),在Awake里放執(zhí)行邏輯要謹(jǐn)慎,特別是AlwaysExecute的組件,所以用菜單功能更能保證安全性,一次創(chuàng)建,永久保存)為了進(jìn)一步保證工具的安全性(雖然現(xiàn)在只有我一個(gè)人在用)我加了一個(gè)提示框:

代碼如下:
3、在場(chǎng)景加載時(shí),更新游戲?qū)ο蟮臓顟B(tài),判定游戲?qū)ο蟮奈ㄒ恍杂蓀ersistStr決定。后面的邏輯都比較順暢了,就不贅述了。
遇到的坑大致如下:
1、InstanceID不能保證對(duì)象唯一性,每次進(jìn)出場(chǎng)景時(shí)值會(huì)發(fā)生變化,必須創(chuàng)建一個(gè)唯一標(biāo)識(shí)的Guid
2、在編輯器中調(diào)用其target指向的類的方法要謹(jǐn)慎,有時(shí)候可能導(dǎo)致游戲運(yùn)行的結(jié)果異常。
3、枚舉enum和字典Dictionary不能被序列化(這里的序列化指C#的[Serializable]),使用二進(jìn)制存檔需要將數(shù)據(jù)分離出來(lái)一個(gè)可以被序列化的類中,所以要保證每個(gè)成員都能被序列化。將不能序列化的enum和Dictionary存儲(chǔ)為可以被序列化的int和List,然后反序列化時(shí)再按照需要組裝成需要的結(jié)構(gòu)。
目前還有一些沒(méi)有完善的地方,比如在3號(hào)地圖打開(kāi)通往1號(hào)地圖的后門(mén)時(shí),需要對(duì)1號(hào)地圖的入口進(jìn)行數(shù)據(jù)操作;至于為什么當(dāng)初沒(méi)有考慮將所有關(guān)卡設(shè)計(jì)為同一張地圖,這個(gè)也是為了讓關(guān)卡之間存在一定的獨(dú)立性,不存在一個(gè)機(jī)制的出現(xiàn),會(huì)出現(xiàn)牽一發(fā)而動(dòng)全身的問(wèn)題。雖然我把這款游戲定義為開(kāi)放世界,但地圖之間的獨(dú)立性還會(huì)分開(kāi)比較好,畢竟第一款游戲,不能在性能問(wèn)題上出現(xiàn)敗筆。