继承关系:
(基类)Object -> ScriptableObject -> EditorWindow -> ScriptableWizard
ScriptableObject:
将数据存储在资源文件中,运行时修改退出也会保存。一般编辑器使用较多。类似通过Serializable + Class + Prefab实现存储数据时候,就可以考虑下能不能用ScriptableObject做成一个真正的资源文件,做法是将继承自ScriptableObject脚本创建为yourselfFileName.asset文件。
- 利用yourselfFileName.asset创建出来的数据是被引用,一旦被修改就会被保存到yourselfFileName.asset
- 类似其他资源,它可以被任何场景引用,即场景间共享
- 在项目之间共享
- 没有其他多余的东西,例如多余的Component
- 只有三个回调函数OnEnable,OnDisable,OnDestroy
优点:
可以保存数据类型多样(int、string、Vector3、GameObject、Transform、Texture等)如关联预设,关联图片等资源数据,而XML、TXT等只能保存(int、string、Vector3 等基本数据类型)。
缺点:
如果配置数据中保存了(GameObject、Texture)等资源数据,当关联的资源被删除时,配置数据将丢失,需要重新将新的资源再次关联到配置数据上。
1.利用继承自ScriptableObject的类创建xxx.assets文件
方法1:
- //CreateAssetMenu 方法用于在上方Asset或Project面板下右键的Create菜单里边下生成创建 CreateMySelfAsset 按钮
- [CreateAssetMenu(fileName = "MyScriptableObject", menuName = "CreateMySelfAsset", order = 1)]
- public class MyScriptableObject : ScriptableObject
- {
- public int value_int;
- public string value_string;
- public AudioClip m_audioClip;
- public Texture2D m_texture;
- public List<MyDataItem> list = new List<MyDataItem>();
- }
//自定义数据类型在继承自ScriptableObject中使用创建.Asset文件时候,
//该类需要加 Serializable 关键字,不然生成的Asset文件的Inspector面板看不到数据
- [System.Serializable]
- public class MyDataItem
- {
- public int keyInt;
- public string valueStr;
- public MyDataItem(int _key,string _value)
- {
- this.keyInt = _key;
- this.valueStr = _value;
- }
- }
方法2:
- MyScriptableObject tempMyDataItem = ScriptableObject.CreateInstance(typeof(MyScriptableObject)) as MyScriptableObject;
- AssetDatabase.CreateAsset(tempMyDataItem, "Assets/MyScriptableObject.asset");
- AssetDatabase.SaveAssets();
效果图:
加载.asset文件:
- MyScriptableObject tempMyscriptable = AssetDatabase.LoadAssetAtPath<MyScriptableObject>("Assets/MyScriptableObject.asset");
- tempMyscriptable.list[0].valueStr = "运行修改了。。。";
EditorWindow 可以结合ScriptableObject使用,在窗口中编辑ScriptableObject创建的.asset数据
展示一个简单的自定义window
- public class CustomWindow : EditorWindow {
- //点击Show MyWindhow显示自定义窗口
- [MenuItem("Window/Show CustomWindow")]
- static void ShowMyWindow()
- {
- CustomWindow myWindow = EditorWindow.GetWindow<CustomWindow>("MySelfWindow");
- myWindow.Show();
- }
- EditorWindow.focusedWindow 当前聚焦窗口
- EditorWindow.mouseOverWindow 当前鼠标移动到哪个窗口
- myWindow.autoRepaintOnSceneChange = true 设置此值,任何窗口有任何变化,就会重绘此窗口
- myWindow.maximized = true 窗口是否可以最大化
- myWindow.wantsMouseMove = true; 是否接收鼠标移动事件,不会自动触发重绘此窗口
- 鼠标移动事件判断 Event.current.type == EventType.mouseMove
- myWindow.Close() 关闭此窗口 myWindow.Focus() 聚焦到此窗口
- myWindow.Focus() 聚焦到此窗口
//创建嵌套窗口,参数分别为id,大小位置,创建子窗口的组件的函数,标题
- public Rect windowRect = new Rect(0, 0, 100, 100);//子窗口的大小和位置
- void OnGUI()
- {
- BeginWindows();
- windowRect = GUILayout.Window(1, windowRect, DoWindow, "子窗口");
- EndWindows();
- }
显示一个通知如下,移除通知 myWindow.RemoveNotification(); 不手动移除,过几秒也会自己消失。。。
- public string
m_notification;
- void OnGUI()
- {
m_notification = EditorGUILayout.TextField(m_notification);
if
(GUILayout.Button(
"显示消息"
))
{
myWindow.ShowNotification(
new
GUIContent(m_notification));
}
}
向其他窗口传递事件(当聚焦到Hierarchy面板时,传递给它一个粘贴的事件)
- void OnGUI()
- {
- if (EditorWindow.focusedWindow.ToString().Trim() == "(UnityEditor.SceneHierarchyWindow)")
- {
- EditorWindow.focusedWindow.SendEvent(EditorGUIUtility.CommandEvent("Paste"));//传递粘贴的事件
- }
- }
ScriptableWizard
显示:
//第一个参数是对话框名称,第二个参数是Create按钮的名字,第三个参数是第二个按钮,点击不会关闭窗口
ScriptableWizard.DisplayWizard<CustomScriptableWizard>("自定义一个对话窗口","按钮1","按钮2");
内置函数:
- OnWizardUpdate() 对话窗口改变自动调用
- OnWizardCreate() 对应上图按钮1点击事件(实测,是关闭按钮?)
- OnWizardOtherButton 对应上图的按钮2点击事件
https://blog.csdn.net/liqiangeastsun/article/details/50510615