特殊模型的数据持久化功能(将模型的数据转换为矩阵数据存储下来)

1、设计模型数据类:需要litjson文件解析数据

using LitJson;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 持久化模型数据类
/// </summary>
public class PersistModelItemData 
{
    
    
    public int Id;//设置id
    public Matrix4x4 TransformMatrix;//4x4矩阵
    public GameObject go;
    public string GoName;

    public PersistModelItemData()
    {
    
    

    }
    public PersistModelItemData(int id, GameObject go)
    {
    
    
        this.Id = id;
        this.go = go;
        this.GoName = go.name;
    }

    /// <summary>
    /// 将物体的三种属性转换成矩阵数据
    /// </summary>
    public void InitMatrix4x4() 
    {
    
     
        Matrix4x4 _mat = new Matrix4x4();
        _mat.SetTRS(go.transform.position, go.transform.rotation, go.transform.localScale);
        TransformMatrix = _mat;
    }

    /// <summary>
    /// 保存json
    /// </summary>
    /// <returns></returns>
    public JsonData ToJson()
    {
    
    
        InitMatrix4x4();
        JsonData jsonData = new JsonData();
        jsonData["Id"] = Id;
        jsonData["GoName"] = GoName;
        jsonData["TransformMatrix"] = MatrixToString(TransformMatrix); 
        return jsonData;
    }

    /// <summary>
    /// 矩阵转换为string数据方法
    /// </summary>
    /// <param name="matrix4X4"></param>
    /// <returns></returns>
    private string MatrixToString(Matrix4x4 matrix4X4 )
    {
    
    
        string str = "";
        str += matrix4X4.m00.ToString() + ",";
        str += matrix4X4.m10.ToString() + ",";
        str += matrix4X4.m20.ToString() + ",";
        str += matrix4X4.m30.ToString() + ",";

        str += matrix4X4.m01.ToString() + ",";
        str += matrix4X4.m11.ToString() + ",";
        str += matrix4X4.m21.ToString() + ",";
        str += matrix4X4.m31.ToString() + ",";

        str += matrix4X4.m02.ToString() + ",";
        str += matrix4X4.m12.ToString() + ",";
        str += matrix4X4.m22.ToString() + ",";
        str += matrix4X4.m32.ToString() + ",";

        str += matrix4X4.m03.ToString() + ",";
        str += matrix4X4.m13.ToString() + ",";
        str += matrix4X4.m23.ToString() + ",";
        str += matrix4X4.m33.ToString();
        return str;
    }

    /// <summary>
    /// 读取Json
    /// </summary>
    /// <returns></returns>
    public void FromJson(JsonData json)
    {
    
    
        this.Id = int.Parse(json["Id"].ToString());
        this.GoName = json["GoName"].ToString();
        //矩阵
        JsonData childJsonData = json["TransformMatrix"];
        this.TransformMatrix = StringToMatrix(childJsonData);
    }


    /// <summary>
    /// 读取的json转换为矩阵数据方法
    /// </summary>
    /// <param name="jsonData"></param>
    /// <returns></returns>

    public Matrix4x4 StringToMatrix(JsonData jsonData)
    {
    
    
        string str = jsonData.ToString();
        string[] strs = str.Split(',');
        Vector4 v1 = new Vector4(float.Parse(strs[0]), float.Parse(strs[1]), float.Parse(strs[2]), float.Parse(strs[3]));
        Vector4 v2 = new Vector4(float.Parse(strs[4]), float.Parse(strs[5]), float.Parse(strs[6]), float.Parse(strs[7]));
        Vector4 v3 = new Vector4(float.Parse(strs[8]), float.Parse(strs[9]), float.Parse(strs[10]), float.Parse(strs[11]));
        Vector4 v4 = new Vector4(float.Parse(strs[12]), float.Parse(strs[13]), float.Parse(strs[14]), float.Parse(strs[15]));
        Matrix4x4 matrix4X4 = new Matrix4x4(v1, v2, v3, v4);
        return matrix4X4;
    }
}



2、存储数据和操作数据的类:

using LitJson;
using RsFramework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Sirenix.OdinInspector;
using YYSUI;
/// <summary>
/// 持久化模型数据
/// </summary>
public class PersistModelDataScript : MonoSingleton<PersistModelDataScript>
{
    
    
    public List<int> IDList = new List<int>();//id列表
    public Dictionary<int, PersistModelItemData> _DicPersistModel = new Dictionary<int, PersistModelItemData>();//id对应的模型数据列表
    // Start is called before the first frame update 
    void Awake()
    {
    
    
        Load();
    }

    private void OnApplicationQuit()
    {
    
    
        Save();
    }

    /// <summary>
    /// 添加到字典集合中
    /// </summary>
    /// <param name="gameObject">表示持久化数据的模型</param>
    public void Add(GameObject go)
    {
    
    
        int id;
        if (IDList.Count == 0)
        {
    
    
            id = 1;
        }
        else
        {
    
    
            id = IDList[IDList.Count - 1] + 1;
        }
        IDList.Add(id);
        PersistModelItemData persistModelItemData = new PersistModelItemData(id, go);
        _DicPersistModel.Add(id, persistModelItemData);
    }

    /// <summary>
    /// 从字典集合中移除模型
    /// </summary>
    /// <param name="gameObject"></param>
    public void Remove(GameObject go)
    {
    
    
        PersistModelItemData persistModelItemData = null;
        foreach (var item in _DicPersistModel.Values)
        {
    
    
            if (go == item.go)
            {
    
    
                persistModelItemData = item;
            }
        }
        if (persistModelItemData != null)
        {
    
    
            Destroy(persistModelItemData.go);
            _DicPersistModel.Remove(persistModelItemData.Id);
            IDList.Remove(persistModelItemData.Id);
        }
    }


    /// <summary>
    /// 加载持久化模型的数据
    /// </summary>
    public void Load()
    {
    
    
        //1、获取保存的路径
        string JsonPath = Application.streamingAssetsPath + "/PersistModelData" + ".json";
        //读取数据,并去除收尾空格
        string jsonStr = File.ReadAllText(JsonPath).Trim();
        //判空
        if (jsonStr.Length != 0)
        {
    
    
            //2、创建json对象,将传过来的数据转换为对象
            JsonData jsonData = JsonMapper.ToObject(jsonStr);

            //单个数据
            //PersistModelItemData persistModelItemData = new PersistModelItemData();
            //persistModelItemData.FromJson(jsonData);
            //MatrixUtils.Matrix4x4(cube2, persistModelItemData.TransformMatrix);

            for (int i = 0; i < jsonData.Count; i++)
            {
    
    
                if (IDList.Contains((int)jsonData[i]["Id"]))
                {
    
    

                }
                else
                {
    
    
                    PersistModelItemData persistModelItemData = new PersistModelItemData();
                    persistModelItemData.FromJson(jsonData[i]);
                    //实例化物体,赋值
                    GameObject go = ResourcesMgr.GetInstance().LoadAsset("PersistModel/" + persistModelItemData.GoName, true);
                    persistModelItemData.go = go;
                    MatrixUtils.Matrix4x4(go.transform, persistModelItemData.TransformMatrix);
                    IDList.Add(persistModelItemData.Id);
                    _DicPersistModel.Add(persistModelItemData.Id, persistModelItemData);
                }
            }
        }
        Debug.Log("加载拖拽模型数据");
    }
    /// <summary>
    /// 存储持久化模型的数据
    /// </summary>
    public void Save()
    {
    
    
        //读取
        string JsonPath = Application.streamingAssetsPath + "/PersistModelData" + ".json";
        //找到当前路径
        FileInfo file = new FileInfo(JsonPath);
        //判断有没有文件,有则打开文件,没有创建后打开文件
        StreamWriter sw = file.CreateText();
        JsonData jsonData = new JsonData();
        foreach (var item in _DicPersistModel.Values)
        {
    
    
            jsonData.Add(item.ToJson());
        }

        //单个数据
        //PersistModelItemData persistModelItemData = new PersistModelItemData(1,cube1.gameObject);

        //将转换好的字符串存进文件
        sw.WriteLine(jsonData.ToJson());
        //注意释放资源
        sw.Close();
        sw.Dispose();
        Debug.Log("保存拖拽模型数据");
    }
}

3、矩阵数据接口,根据矩阵数据获取到模型设置的位置、旋转和缩放:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 矩阵接口,获取物体的位置,旋转和缩放
/// </summary>
internal static class MatrixUtils
{
    
    
    public static void Matrix4x4(this Transform transfrom, Matrix4x4 matrix4X4)
    {
    
    
        transfrom.localScale = matrix4X4.GetScale();
        transfrom.rotation = matrix4X4.GetRotation();
        transfrom.position = matrix4X4.GetPosition();
    }

    /// <summary>
    /// 根据矩阵数据获得scale数据
    /// </summary>
    /// <param name="m"></param>
    /// <returns></returns>
    public static Vector3 GetScale(this Matrix4x4 m)
    {
    
    
        var x = Mathf.Sqrt(m.m00 * m.m00 + m.m01 * m.m01 + m.m02 * m.m02);
        var y = Mathf.Sqrt(m.m10 * m.m10 + m.m11 * m.m11 + m.m12 * m.m12);
        var z = Mathf.Sqrt(m.m20 * m.m20 + m.m21 * m.m21 + m.m22 * m.m22);
        return new Vector3(x, y, z);
    }

    /// <summary>
    /// 根据矩阵数据获得position数据
    /// </summary>
    /// <param name="m"></param>
    /// <returns></returns>
    public static Vector3 GetPosition(this Matrix4x4 matrix4X4) 
    {
    
    
        var x = matrix4X4.m03;
        var y = matrix4X4.m13;
        var z = matrix4X4.m23;
        return new Vector3(x, y, z);
    }

    /// <summary>
    /// 根据矩阵数据获得rotation数据
    /// </summary>
    /// <param name="m"></param>
    /// <returns></returns>
    public static Quaternion GetRotation(this Matrix4x4 matrix4X4)
    {
    
    
        float qw = Mathf.Sqrt(1f + matrix4X4.m00 + matrix4X4.m11 + matrix4X4.m22) / 2;
        float w = 4 * qw;
        float qx = (matrix4X4.m21 - matrix4X4.m12) / w;
        float qy = (matrix4X4.m02 - matrix4X4.m20) / w;
        float qz = (matrix4X4.m10 - matrix4X4.m01) / w;
        return new Quaternion(qx, qy, qz, qw);
    }
}

4、对象池使用:

/*
 *		内容:UI框架
 *		功能:资源加载管理器,增加缓存,不重复加载
 */
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;


namespace YYSUI
{
    
    
    public class ResourcesMgr : MonoBehaviour
    {
    
    
        /* 字段 */
        private static ResourcesMgr _Instance;              //本脚本私有单例实例
        private Hashtable ht = null;                        //容器键值对集合
        /// <summary>
        /// 得到实例(单例)
        /// </summary>
        /// <returns></returns>
        public static ResourcesMgr GetInstance()
        {
    
    
            if (_Instance == null)
            {
    
    
                _Instance = new GameObject("_ResourceMgr").AddComponent<ResourcesMgr>();
            }
            return _Instance;
        }

        void Awake()
        {
    
    
            ht = new Hashtable();
        }

        /// <summary>
        /// 调用资源(带对象缓冲技术)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="isCatch"></param>
        /// <returns></returns>
        public T LoadResource<T>(string path, bool isCatch) where T : UnityEngine.Object
        {
    
    
            if (ht.Contains(path))
            {
    
    
                return ht[path] as T;
            }

            T TResource = Resources.Load<T>(path);
            if (TResource == null)
            {
    
    
                Debug.LogError(GetType() + "/Resource 提取的资源找不到,请检查。 path=" + path);
            }
            else if (isCatch)
            {
    
    
                ht.Add(path, TResource);
            }
            return TResource;
        }

        /// <summary>
        /// 调用资源(带对象缓冲技术)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="isCatch"></param>
        /// <returns></returns>
        public GameObject LoadAsset(string path, bool isCatch)
        {
    
    
            GameObject goObj = LoadResource<GameObject>(path, isCatch);
            GameObject goObjClone = GameObject.Instantiate<GameObject>(goObj);
            goObjClone.name = goObj.name;
            if (goObjClone == null)
            {
    
    
                Debug.LogError(GetType() + "/LoadAsset()/克隆资源不成功,请检查。 path=" + path);
            }
            //goObj = null;//??????????
            return goObjClone;
        }

        public T LoadAsset<T>(string path, bool isCatch) where T : UnityEngine.Object
        {
    
    
            T goObj = LoadResource<T>(path, isCatch);
            T goObjClone = GameObject.Instantiate<T>(goObj);
            if (goObjClone == null)
            {
    
    
                Debug.LogError(GetType() + "/LoadAsset()/克隆资源不成功,请检查。 path=" + path);
            }
            //goObj = null;//??????????
            return goObjClone;
        }
    }//Class_end
}

5、使用范例:
5.1:将特殊的模型设置成预制件,放到Resources对应的文件夹下
5.2:在合适的时候实例化特殊的模型,加入到数据字典中(PersistModel是我自己设置的文件夹路径,modelName表示特殊模型预制件的名称与数据中保存的一一对应)
在这里插入图片描述

在这里插入图片描述
做这一步操作是为了确保程序开始加载数据的时候不会出错,外边套一个gameobject,设置如下,里边的暂没有要求
在这里插入图片描述

obj = ResourcesMgr.GetInstance().LoadAsset("PersistModel/" + modelName, true);

加入到数据字典中语句

 PersistModelDataScript.Instance.Add(obj);

5.3:在合适的时候调用删除方法,将模型数据移除出数据字典中,移除出数据字典中语句(transformGizmo.target.gameObject表示移除的特殊模型gameobject)

PersistModelDataScript.Instance.Remove(transformGizmo.target.gameObject);

5.4保存的数据如下:

[
  {
    
    
    "Id": 1,
    "GoName": "SGBZ_ZBP",
    "TransformMatrix": "1,0,0,0,0,1,0,0,0,0,1,0,60.1446,-3.257808E-17,73.35932,1"
  },
  {
    
    
    "Id": 2,
    "GoName": "SGBZ_AQWL",
    "TransformMatrix": "1,0,0,0,0,1,0,0,0,0,1,0,60.4089,-3.604125E-17,81.15768,1"
  }
]


5.5、要想程序一开始就执行此代码,需要调用此代码或者将PersistModelDataScript脚本挂载到场景中,就可以实现程序开始记录需要保存的特殊模型的数据,在重新打开程序时,会自动读取之前的模型数据。

猜你喜欢

转载自blog.csdn.net/qq_37179591/article/details/125116566