【Untiy3d-編輯器相關4】ScriptableObject,EditorWindow,ScriptableWizard
繼承關係:
(基類)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