使用scriptableobject存储物体状态信息

最近有一个需求,就是要记录游戏物体在不同状态下的位置信息,一个物体有任意多种状态(可能是一种或n种),则想到了用scriptableobject来存储,写出了这样一个scriptableobject类。

以下为存储物体状态类:

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

/// <summary>
/// 物体状态结构体
/// </summary>
[Serializable]//序列化,才能显示在层次面板上
public struct ObjectStateStruct
{
    //物体状态
    public string objectState;
    //物体位置
    public Vector3 Pos;
    //物体角度            
    public Vector3 Rot;
    //物体大小
    public Vector3 Sca;
    public ObjectStateStruct(string objectState, Transform transform)
    {
        this.objectState = objectState;
        Pos = transform.position;
        Rot = transform.eulerAngles;
        Sca = transform.localScale;
    }
}
[CreateAssetMenu(fileName = "ObjectStore", menuName = "MySubMenu/NewObjectStore", order = 0)]
public class ObjectStore : ScriptableObject
{
    public List<ObjectStateStruct> Objects;
}

在Project窗口右键新建一个储物体状态类的实例:

得到下面一个结果,可以存贮物体的位置信息,但是人力输入不现实,所以还要用一个类去创建与更新的储物体状态类的实例:

 实现思路为读取游戏对象列表信息,依次创建与更新scriptableobject实例化出来的文件:

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

public class Create : MonoBehaviour
{
    public string folder=default;
    public List<GameObject> RecordObjectList;

    void CreateAsset(string ObjectName,Transform m_tr)
    {
        //资源路径
        string path = "Assets/DataBase/"+ folder + "/" + ObjectName + ".asset";
        ObjectStore readObjectAsset = AssetDatabase.LoadAssetAtPath<ObjectStore>(path);
        //读取不到则创建
        if (!readObjectAsset)
        {
            ObjectStore objectAsset = ScriptableObject.CreateInstance<ObjectStore>();
            objectAsset.Objects = new List<ObjectStateStruct>();
            objectAsset.Objects.Add(new ObjectStateStruct(ObjectName + "Init", m_tr));
            AssetDatabase.CreateAsset(objectAsset, path);
            //刷新编辑器,使刚创建的资源立刻被导入,才能接下来立刻使用上该资源
            AssetDatabase.Refresh();
        }
        else
        {
            if (readObjectAsset.Objects.Count == 0)
                readObjectAsset.Objects.Add(new ObjectStateStruct(ObjectName + "InitAA", m_tr));//读取到,若为零则添加新记录
            else if (ListEquals(readObjectAsset, m_tr))
                readObjectAsset.Objects.Add(new ObjectStateStruct(ObjectName + "Add", m_tr));//读取到,若与其它记录不一样则添加新记录
            // 通知编辑器有资源被修改了
            EditorUtility.SetDirty(readObjectAsset);
            //保存所有修改
            AssetDatabase.SaveAssets();
        }
    }
    //列表元素是否相同
    bool ListEquals(ObjectStore readObjectAsset,Transform m_tr)
    {
        foreach (var obj in readObjectAsset.Objects)
        {
            if (obj.Pos == m_tr.position && obj.Rot == m_tr.eulerAngles && obj.Sca == m_tr.localScale)
                return false;
        }
        return true;
    }

    //创建资源
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            foreach (GameObject obj in RecordObjectList)
            {
                CreateAsset(obj.name, obj.transform);
            }

            Debug.Log("已保存");
        }
    }

}

需要在Assets文件中提前创建DataBase文件夹,Create脚本需要挂游戏物体,先要记录的游戏对象挂到Create的List上去,按S键保存。

猜你喜欢

转载自blog.csdn.net/qq_39858654/article/details/126989762