最近项目里面有这样一个需求,就是把场景里面的东西保存下载,然后需要的时候读取数据,加载出来。
这里用到了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场景。