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

    xiaoxiao2022-07-14  160

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

    这里用到了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场景。

    最新回复(0)