Unity3D——遊戲序列化

說在前面

    序列化是爲了將對象存儲(或傳輸)到內存、數據庫或文件中,把對象狀態轉化爲一組字節的過程。換句話說:就是如何保存對象並恢復其狀態以供後續使用。現在的遊戲一般都離不開序列化,特別是一些大型遊戲,因爲遊戲本身就非常大,每次版本更新就去重裝一次顯然不現實。而遊戲系列化就能很好的解決這個矛盾,通過比對服務器上的文本數據來判斷玩家是否需要更新。


實現

    以之前寫過的一個簡單的打飛碟遊戲爲基礎,實現將其的序列化

    首先在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;  
			}  
		} 

最後看看簡單效果:



發佈了37 篇原創文章 · 獲贊 121 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章