Unity3D游戏序列化以及新版本发布

序列化技术:
序列化 就是把一个内存对象变为与地址无关的可传输的数据格式,通常是文本格式;反序列化反之。

一般情况下,对象序列化指把一个对象用 XML,YAML 或 json 文本表示。 尽管 Unity 场景文件是 yaml 格式的,但并没有提供运行时内置支持。

Unity 已内置 json 支持。
在U3D中使用Serializable标签来标识可序列化对象

[Serializable]
public class MyClass
{
    public int level;
    public float timeElapsed;
    public string playerName;
}

在一个 monoBehavior 中,添加上述类,[Serializable]标签,说明这个类可以被序列化。

U3D中内置了JsonUtility类,用于支持对象的序列化与反序列化,这个类主要包括三个方法

  • FromJson 用 Json 数据实例化一个新对象
  • FromJsonOverwrite 用 Json 数据重新赋值一个对象
  • ToJson 将对象变成一个字符串

下面具体讲一下利用序列化技术发布新的游戏版本

我们采用之前做得飞碟设计游戏作为例子
每次开始游戏之前会读取远程控制目录的游戏版本文件,如果发现与当前的版本不一致就会更新游戏,如果游戏版本没变,则会进入到上次退出游戏时的状态,能够看到上次退出时的分数和轮数

首先是远程控制目录,我设置的是D:\UnityVersionData文件夹
每个版本的文件夹下面有多个json文件,包括一个game_info文件和多个disk_level文件
版本文件

game_info文件包含游戏的版本号以及当前总的轮数:
disk_info文件包括每一轮游戏的各种设置参数,例如射出的飞碟数,飞碟颜色,初速度,入射角度等

新建C#脚本,用于版本控制
声明用于序列化的对象

[Serializable]
    public class GameInfo : System.Object {
        public string version;
        public int totalRound;
    }

    [Serializable]
    public class LevelInfo:System.Object {
        public int round;
        public int UFO_total_num;
        public string color;
        public float disk_scale;
        public float speed;
        public float lanuch_position_Y;
        public float lanuch_angle;
    }

这两个对象分别对应json文件里的对象(注意,这里的对象类型必须是JsonUtility能够解析的对象类型,主要是各种基础类型,如果有类成员变量,需要将这个类单独进行序列化,不然无法解析)

声明一个版本管理类,使用单例模式,用于管理版本信息

public class DictManager : System.Object {
        private static DictManager _instance;
        private static readonly string gameversion = "version";
        private static readonly string gameround = "totalRound";
        //最多10轮
        private static readonly string[] disk_level = new string[]{
  "disk_level_1", "disk_level_2", "disk_level_3", 
            "disk_level_4", "disk_level_5", "disk_level_6", "disk_level_7", "disk_level_8", "disk_level_9", "disk_level_10"};
        private static readonly string currentRound = "currentRound";
        private static readonly string currentScore = "currentScore";

        public static DictManager getInstance() {
            if (_instance == null)
                _instance = new DictManager ();
            return _instance;
        }

        //保存版本信息
        public void setVersion(string version) {
            PlayerPrefs.SetString (gameversion, version);
        }

        public string getVersion() {
            return PlayerPrefs.GetString(gameversion, "none");
        }

        //保存总的游戏轮数
        public void setTotalGround(int totalRound) {
            PlayerPrefs.SetInt (gameround, totalRound);
        }

        public int getTotalRound() {
            return PlayerPrefs.GetInt (gameround, 0);
        }

        //保存当前轮数的游戏信息
        public void setLevelInfo(int index, string text) {
            PlayerPrefs.SetString (disk_level [index], text);
        }

        public void cleanLevelInfo(int index) {
            while (index < 10 && PlayerPrefs.HasKey (disk_level [index])) {
                PlayerPrefs.DeleteKey (disk_level [index]);
                index++;
            }
        }

        public string getLevelInfo(int index) {
            return PlayerPrefs.GetString (disk_level [index], "none");
        }

        //保存当前轮数
        public void setCurrentRound(int Round) {
            PlayerPrefs.SetInt (currentRound, Round);
        }

        public int getCurrentRound() {
            return PlayerPrefs.GetInt (currentRound);
        }

        //保存当前分数
        public void setCurrentScore(int Score) {
            PlayerPrefs.SetInt (currentScore, Score);
        }

        public int getCurrentScore() {
            return PlayerPrefs.GetInt (currentScore);
        }

    }

这个管理类中使用了PlayerPrefs类,他的作用是保存游戏Session之间的数据,从代码中可以发现,这个其实就是一个字典,他以key-value的方式持久化数据,一般来说,这个类适合用来存储与现场恢复相关的数据,类似于web开发中的session和cookie,关于PlayerPrefs类的具体用法可以参考
http://docs.unity3d.com/ScriptReference/PlayerPrefs.html

注意到这里使用了一个单例类来管理这个字典,并且字典是注入式的,这样就很好的解决了字典的同步问题,也降低了代码的耦合度,这里采用了OO设计原则

接下来是关于json文件加载,这里使用MonoBehavior的类来加载文件
这里需要使用WWW类,这是一个万能类,支持HTTP,HTTPS, file, jar:file等协议,由于加载文件属于IO操作(如果使用HTTP等协议还可能是网络操作),所以会阻塞当前线程,显然我们不能在主线程里面加载,但是U3D又不能像JAVA一样支持多进程多线程,那怎么办呢?当然是使用协程了!协程可以显式的调用中断,我们只要在加载文件出设置中断就可以了,直到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值