說在前面
序列化是爲了將對象存儲(或傳輸)到內存、數據庫或文件中,把對象狀態轉化爲一組字節的過程。換句話說:就是如何保存對象並恢復其狀態以供後續使用。現在的遊戲一般都離不開序列化,特別是一些大型遊戲,因爲遊戲本身就非常大,每次版本更新就去重裝一次顯然不現實。而遊戲系列化就能很好的解決這個矛盾,通過比對服務器上的文本數據來判斷玩家是否需要更新。
實現
以之前寫過的一個簡單的打飛碟遊戲爲基礎,實現將其的序列化
首先在Assets視圖中創建文件夾Data,並將存放遊戲版本與關卡信息的json文件,如下:
原先的關卡信息存放在GameController.cs中,現在已經序列化了,這個類原先的實現就沒有用處的,可以將其實現清空,然後再在其後添加兩個帶有[SerializeField]符號的類,一個存放關卡信息,一個存放版本信息,用於類的可序列化:
[SerializeField]
public class GameInfo
{
public string version;
public int totalRound;
public static GameInfo CreateFromJSON(string json)
{
return JsonUtility.FromJson<GameInfo>(json);
}
}
[SerializeField]
public class LevelData
{
public float speed;
public int round;
public static LevelData CreateFromJSON(string json)
{
return JsonUtility.FromJson<LevelData>(json);
}
}
接着創建一個FileManager的cs腳本,用於處理文本的讀寫:
using UnityEngine;
using System.Collections;
using Com.Mygame;
using Com.GameControllers;
public class FileManager : MonoBehaviour {
public string url;
private GameController scene= GameController.getInstance();
void Awake()
{
scene = GameController.getInstance();
scene.setFileManager(this);
LoadGameInfoJson("disk_game.json"); // 獲取遊戲版本等信息
}
// 輸入關卡文件名,啓動協程讀取文件
public void loadLevelJson(string name)
{
url = "file://" + Application.dataPath + "/Data/" + name;
StartCoroutine(LoadLevel());
}
IEnumerator LoadLevel()
{
if (url.Length > 0)
{
WWW www = new WWW(url);
yield return www;
if (!string.IsNullOrEmpty(www.error))
Debug.Log(www.error);
else
scene.stageLevel(www.text.ToString()); // 返回json字符串給scene
}
}
// 輸入遊戲信息文件名,啓動協程讀取文件
public void LoadGameInfoJson(string name)
{
url = "file://" + Application.dataPath + "/Data/" + name;
StartCoroutine(LoadGameInfo());
}
IEnumerator LoadGameInfo()
{
if (url.Length > 0)
{
WWW www = new WWW(url);
yield return www;
if (!string.IsNullOrEmpty(www.error))
Debug.Log(www.error);
else
scene.stageGameInfo(www.text.ToString()); // 返回json字符串給scene
}
}
}
爲了在屏幕上顯示版本信息,因此需要更改UI腳本,類似這樣:
另外,遊戲的關卡是遊戲過程中讀取的,我將關卡信息放在rules.cs中,所以現在需要修改調用下一Round的函數:
public void passLever() {
my = GameController.getInstance();
if (++lever > my._totalRound) {
lever = 1; // 循環
}
string file = "disk_level_" + lever.ToString() + ".json";
my.getFileManager().loadLevelJson(file);
}
最後,還需要修改GameController.cs,比如添加FileManager的註冊函數和調用函數;添加stageLevel和stageGameinfo用於接收json字符串並將其轉化爲對應的遊戲參數:
private FileManager _fileManager;
public string _version;
public void stageGameInfo(string json) {
GameInfo data = GameInfo.CreateFromJSON(json);
_version = data.version;
_totalRound = data.totalRound;
}
public void stageLevel(string json) {
LevelData data = LevelData.CreateFromJSON(json);
rule.speed = data.speed;
rule.lever = data.round;
}
public FileManager getFileManager() {
return _fileManager;
}
internal void setFileManager(FileManager ggo) {
if (null == _fileManager) {
_fileManager = ggo;
}
}
最後看看簡單效果: