最近有一个需求,就是要记录游戏物体在不同状态下的位置信息,一个物体有任意多种状态(可能是一种或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键保存。