Unity 编辑器扩展总结 八:EditorPrefs、ScriptableObject、Undo

编辑器扩展总结

工欲善其事必先利其器

引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。如若博客中存在错误,还请不吝赐教。所有参考的博客或者视频来源将在文末展示。
开发版本: Unity 2019.4.9f1

相关博客传送门
一、编辑器开发入门

二、编辑器的相关特性

三、自定义Inspector面板

四、创建编辑器窗体

五、Gizmos辅助调试工具

六、扩展Scene视图

七、数组或list集合的显示方式

八、EditorPrefs、ScriptableObject、Undo

九、GUIStyle、GUISkin

十、AssetPostprocessor资源导入管线

EditorPrefs、ScriptableObject、Undo

EditorPrefs的简单使用

Unity编辑器为开发者提供了类似PlayerPrefs的数据保存方式EditorPrefs。EditorPrefs是适用于编辑器模式,而PlayerPrefs适用于游戏运行时。
EditorPrefs提供了四种数据的保存:int,float,string,bool
通过Set方法保存下数据,下次则通过Get方法来获取数据,HasKey方法可以判断是否存在该数据的保存,删除数据调用DeleteKey方法即可。

示例:

using UnityEngine;
using UnityEditor;

public class WindowExample2 : EditorWindow
{
    private static WindowExample2 window;//窗体实例
    private string tempMsg;

    //显示窗体
    [MenuItem("MyWindow/Second Window")] 
    private static void ShowWindow()
    {
        window = EditorWindow.GetWindow<WindowExample2>("Window Example");
        window.Show();
    }

    private void OnEnable()
    {
        if (EditorPrefs.HasKey("TempMsg"))
        {
            tempMsg = EditorPrefs.GetString("TempMsg");
        }
    }

    private void OnGUI()
    {
        tempMsg = EditorGUILayout.TextField("Temp Msg", tempMsg);
        if (GUILayout.Button("Save"))
        {
            EditorPrefs.SetString("TempMsg", tempMsg);
        }
    }
}

注意:需要谨慎调用EditorPrefs.DeleteAll()方法,因为该方法还可能会删除Unity编辑器自身存储的一些数据,给开发者带来不必要的麻烦。

ScriptableObject

创建ScriptableObject
只需要继承自ScriptableObject,然后在类中定义需要的数据即可。
在类前可以添加CreateAssetMenu属性,方便开发者在Project面板右键Create创建该资源。

using UnityEngine;

[CreateAssetMenu(fileName = "MyData", menuName = "Custom/MyDataAsset", order = 1)]
public class MyData : ScriptableObject 
{
    public int id;
    public string objName;
    public float value;
    public bool isUsed;
}

也可以通过方法调用来创建资源,最终得到的资源是一样的,该脚本需要放在Editor文件夹中。

using System.IO;
using UnityEditor;
using UnityEngine;

public class DataEditor
{
    public static void CreateAsset()
    {
        //生成一个实例对象
        MyData asset = ScriptableObject.CreateInstance<MyData>();
        //创建资源
        AssetDatabase.CreateAsset(asset, Path.Combine(Application.dataPath, "MyData.asset"));
        //保存资源
        AssetDatabase.SaveAssets();
    }
}

使用ScriptableObject
可以将创建的资源放在Resources文件夹中,通过动态的方式加载。

using UnityEngine;

public class Test : MonoBehaviour
{
    private MyData myData;

    private void Start()
    {
        myData = Resources.Load<MyData>("MyData");
        Debug.Log(myData.id);
        Debug.Log(myData.objName);
        Debug.Log(myData.value);
        Debug.Log(myData.isUsed);
    }
}

数据不能保存的情况
如果遇到ScriptableObject数据不能正常保存的情况,可以尝试使用EditorUtility.SetDirty方法,标记该ScriptableObject为“脏”,然后就能正常保存了。

Undo

Undo用于编辑器模式下的撤销操作,这里介绍几种常用的API。

Undo.RegisterCreatedObjectUndo : 记录新建的对象状态,可以撤销新建的对象
Undo.RecordObject:记录对象的状态,需要在修改之前调用
Undo.AddComponent:可以撤销新挂载的组件
Undo.DestroyObjectImmediate:可以撤销删除对象的操作
Undo.SetTransformParent:可以撤销修改父对象的操作

示例:

using UnityEditor;
using UnityEngine;

public class UndoTest
{
    [MenuItem("Tools/Create Obj")]
    private static void CreateObj()
    {
        GameObject newObj = new GameObject("Undo");
        Undo.RegisterCreatedObjectUndo(newObj, "CreateObj");
    }

    [MenuItem("Tools/Move Obj")]
    private static void MoveObj() 
    {
        //获取选中的场景对象
        Transform trans = Selection.activeGameObject.transform;
        if (trans)
        {
            Undo.RecordObject(trans, "MoveObj");
            trans.position += Vector3.up;
        }
    }

    [MenuItem("Tools/AddComponent Obj")]
    private static void AddComponentObj() 
    {
        //获取选中的场景对象
        GameObject selectedObj = Selection.activeGameObject;
        if (selectedObj)
        {
            Undo.AddComponent(selectedObj,typeof(Rigidbody));
        }
    }

    [MenuItem("Tools/Destroy Obj")]
    private static void DestroyObj()
    {
        //获取选中的场景对象
        GameObject selectedObj = Selection.activeGameObject;
        if (selectedObj)
        {
            Undo.DestroyObjectImmediate(selectedObj);
        }
    }

    [MenuItem("Tools/SetParent Obj")]
    private static void SetParentObj()
    {
        //获取选中的场景对象
        Transform trans = Selection.activeGameObject.transform;
        Transform root = Camera.main.transform;
        if (trans)
        {
            Undo.SetTransformParent(trans, root, trans.name);
        }
    }
}

参考资料

Unity Undo(撤销)详解

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值