MessagePack For C#在Unity中的应用(场景的保存和加载)

最近项目里面有这样一个需求,就是把场景里面的东西保存下载,然后需要的时候读取数据,加载出来。

这里用到了MessagePack For C# 的Unity 版本, 先放一个网址https://www.cnblogs.com/Leo_wl/p/8143259.html

如果嫌烦不想看,也用不到这么多功能的话我直接给一个网址下载Unity版本的MessagePack For C#,然后直接上实例,

网址:https://github.com/neuecc/MessagePack-CSharp/releases, 下载Ver 1.7.3.5 就行。下载出来是一个.unitypackage,直接导入Unity就行。

------------------------------------------------------------------

OK,到此为止环境算是配置完成了。这里再说一下我要干什么:把场景中的物体的Transform等一些属性保存下来,然后以二进制的形式存入文件,最后可以通过点击按钮把文件中的信息解析出来,实例化预制体,把解析出来的数据赋值给预制体,实现场景的保存与加载。

第一步:定义数据结构

using System.Collections.Generic;
using MessagePack;  //引入MessagePack包(必须)

[MessagePackObject]//代表需要序列化的对象信息(必须)
public class ItemData
{
    [Key(0)] //每一个属性都要有一个Key,从0到n(必须)
    public List<string> Name = new List<string>(); //名字
    [Key(1)]
    public List<int> Layer = new List<int>();  //层级

    #region  transform  //这下面是物体的Transform信息
    [Key(2)]
    public List<float> position_x = new List<float>();
    [Key(3)]
    public List<float> position_y = new List<float>();
    [Key(4)]
    public List<float> position_z = new List<float>();
    [Key(5)]
    public List<float> rotation_x = new List<float>();
    [Key(6)]
    public List<float> rotation_y = new List<float>();
    [Key(7)]
    public List<float> rotation_z = new List<float>();
    [Key(8)]
    public List<float> scale_x = new List<float>();
    [Key(9)]
    public List<float> scale_y = new List<float>();
    [Key(10)]
    public List<float> scale_z = new List<float>();
    #endregion
}

第二步:写一个方法来保存场景中的对象信息

public void SaveItemData()
    {
        AllItemObj = FindObjectsOfType(typeof(GameObject)) as GameObject[]; //找到场景中所有的GameObject类型的对象
        ItemData itemData = new ItemData(); //实例化一个ItemData用来存值
        foreach (GameObject child in AllItemObj)
        {
            if (child.gameObject.layer == 10)  //10: Ornament   找到层级为10的GameObject
            {
                //Debug.Log(child.gameObject.name); //这里可以打印出名字试一试
                itemData.Name.Add(child.gameObject.name);  //这下面是保存每一个物体的Transform信息
                itemData.Layer.Add(child.gameObject.layer);
                itemData.position_x.Add(child.gameObject.transform.position.x);
                itemData.position_y.Add(child.gameObject.transform.position.y);
                itemData.position_z.Add(child.gameObject.transform.position.z);
                itemData.rotation_x.Add(child.gameObject.transform.rotation.eulerAngles.x);
                itemData.rotation_y.Add(child.gameObject.transform.rotation.eulerAngles.y);
                itemData.rotation_z.Add(child.gameObject.transform.rotation.eulerAngles.z);                
                itemData.scale_x.Add(child.gameObject.transform.localScale.x);
                itemData.scale_y.Add(child.gameObject.transform.localScale.y);
                itemData.scale_z.Add(child.gameObject.transform.localScale.z);
            }
        }
        //注意:这里用到了MessagePack的序列化方法把ItemData类型的itemData对象序列化为一个byte数组
        var byteData = MessagePackSerializer.Serialize<ItemData>(itemData);
        //必须要在Unity中工程中创建一个StreamingAssets的文件夹
        string path = Application.streamingAssetsPath + "/"; 
        //保存数据的文件的名字
        string name = "ItemData";
        //把数据全部写入文件中
        File.WriteAllBytes(path + name, byteData);
        Debug.Log("保存完毕");
    }

这里我是用一个按钮来触发这个方法。

第三步:加载保存的对象信息,实现加载场景

 public void LoadItemData()
    {
        UnityEngine.Object itemObj;
        GameObject IObj = null;
        string path = Application.streamingAssetsPath + "/";
        string name = "ItemData";
        string itemPath = "Models/FBX/";
        byte[] readByte;
        if (File.Exists(path + name))
        {
            readByte = File.ReadAllBytes(path + name);
            Debug.Log("读取数据完毕");
        }
        else
        {
            Debug.Log("没找到路径,当前得到的路径是: " + path + name);
            return;
        }  
        ItemData itemData = new ItemData();
        //注意:这里用到了MessagePack的反序列化方法,这里是把readByte以ItemData的类型反序列化出来,赋值给itemData
        itemData = MessagePackSerializer.Deserialize<ItemData>(readByte);
        for(int i = 0; i < itemData.Name.Count; i++) //把序列化出来的数据传给每一个预制体
        {
            string nameNoNum = RemoveNumber(itemData.Name[i]);
            itemObj = Resources.Load(itemPath + nameNoNum, typeof(GameObject));
            IObj = Instantiate(itemObj) as GameObject; //实例化预制体
            IObj.name = itemData.Name[i];
            IObj.layer = itemData.Layer[i];

            IObj.transform.position = new Vector3(itemData.position_x[i], itemData.position_y[i], itemData.position_z[i]);
            IObj.transform.rotation = Quaternion.Euler(new Vector3(itemData.rotation_x[i], itemData.rotation_y[i], itemData.rotation_z[i]));
            IObj.transform.localScale = new Vector3(itemData.scale_x[i], itemData.scale_y[i], itemData.scale_z[i]);
        }
        Debug.Log("加载完毕");
    }

这个方法我也是通过在场景中点击按钮实现。

好了到这里为止,实现了使用MessagePack For C#保存和加载Unity场景。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值