我正在嘗試為我的序列類制作一個自定義檢查器。這個想法是允許用戶配置在序列開始或結束時呼叫的各種 UnityEvent。
我想在 ReorderableList 中有一個序列集合,以便它在檢查器中高度可配置。
我非常接近解決方案,但我對編輯器腳本相當缺乏經驗。我的腳本幾乎可以正常作業。但是我仍然需要解決動態調整每個專案的垂直高度的最佳方法,在 DrawListItem 方法中,以及在 ElementHeight 方法中的總垂直高度。
我正在考慮嘗試反序列化統一事件,以便我可以使用 GetPersistentEventCount 方法來了解所需的垂直高度,但這似乎有點矯枉過正。我懷疑必須有一種更簡單的方法來檢索這些資料。
目前,當我將多個專案添加到序列中時,我得到了下圖所示的內容,其中事件欄位相互重疊,添加/洗掉按鈕位于較低的 Unity 事件下方。
有誰知道解決這個問題的最佳方法?

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System;
using UnityEngine.Events;
[CustomEditor(typeof(SequenceManager))]
public class SequenceManagerEditor : Editor
{
SerializedProperty Sequences;
ReorderableList list;
private void OnEnable()
{
Sequences = serializedObject.FindProperty("Sequences");
list = new ReorderableList(serializedObject, Sequences, true, true, true, true);
list.drawElementCallback = DrawListItems;
list.drawHeaderCallback = DrawHeader;
list.elementHeightCallback = ElementHeight;
}
//Draws the elements in the list
void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty element = list.serializedProperty.GetArrayElementAtIndex(index);
////NAME
EditorGUI.LabelField(new Rect(
rect.x,
rect.y EditorGUIUtility.standardVerticalSpacing,
50,
EditorGUIUtility.singleLineHeight), "Name");
EditorGUI.PropertyField(
new Rect(
rect.x 50,
rect.y EditorGUIUtility.standardVerticalSpacing,
rect.width - 50,
EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("Name"),
GUIContent.none
);
//ON INIT
EditorGUI.LabelField(new Rect(
rect.x,
rect.y EditorGUIUtility.singleLineHeight EditorGUIUtility.standardVerticalSpacing * 3,
50,
EditorGUIUtility.singleLineHeight), "OnInit");
EditorGUI.PropertyField(new Rect(
rect.x 50,
rect.y EditorGUIUtility.singleLineHeight EditorGUIUtility.standardVerticalSpacing * 3,
rect.width - 50,
3 * rect.y 5 * EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("OnInit"),
GUIContent.none);
//ON DONE
EditorGUI.LabelField(new Rect(
rect.x,
rect.y 7 * EditorGUIUtility.singleLineHeight,
50,
EditorGUIUtility.singleLineHeight), "OnDone");
EditorGUI.PropertyField(
new Rect(
rect.x 50,
rect.y 7 * EditorGUIUtility.singleLineHeight,
rect.width - 50,
3 * rect.y 12 * EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("OnDone"),
GUIContent.none);
SerializedProperty indexProperty = element.FindPropertyRelative("index");
indexProperty.intValue = index;
}
private float ElementHeight(int index)
{
return (13 * EditorGUIUtility.singleLineHeight);
}
//Draws the header
void DrawHeader(Rect rect)
{
string name = "Sequences";
EditorGUI.LabelField(rect, name);
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
this.list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
為了完整起見,我還在下面添加了 Sequence 類和 SequenceManager 類。
using UnityEngine;
using UnityEditor;
using System;
using UnityEngine.Events;
[Serializable]
public class Sequence
{
public string Name;
public UnityEvent OnInit;
public UnityEvent OnDone;
private Module _module;
public int index;
private bool active;
//Called By The Sequence Manager At the start of a sequence
internal void Init(Module p_module)
{
Debug.Log($"sequence: {Name} with index: {index} has started");
active = true;
_module = p_module;
if(OnInit.HasNoListners())
{
Done();
}
else
{
OnInit.Invoke();
}
}
//Called Manually to Trigger the End of the Sequence
internal void Done()
{
if (!OnDone.HasNoListners())
{
OnDone.Invoke();
}
active = false;
Debug.Log($"sequence: {Name} with index: {index} is done");
_module.FinishedSequence(index);
}
//Check if active
internal bool GetActive()
{
return active;
}
}
using System;
namespace UnityEngine
{
[Serializable]
public class SequenceManager: MonoBehaviour
{
#region Properties
public Sequence[] Sequences;
#endregion
}
}
uj5u.com熱心網友回復:
可以通過在編輯器腳本中Sequence轉換元素來訪問公共欄位。serializedObject.targetObjects您也可以使用serializedObject.targetObjector
如果您更愿意更改Sequence通常在 Inspector 中繪制 a 的方式,那么您最好實作自定義PropertyDrawer而不需要處理串列。
And the drawer dealing with the index is btw dangerous / not reliable!
Currently your index is only applied if this is actually opened in the Inspector and not in Debug mode. What if later you want to modify this via script?
In my opinion it would be better if your SequenceManager rather simply passes in the index into the Init method if it is really needed for anything except the log ;)
Also be very careful: In your Sequence script you have
using UnityEditor;
be aware that this namespace is only available within the Unity editor itself and completely stripped of during the build.
=> You want to make sure that nothing of this namespace is trying to be used in a built application so you will have to wrap any references to this namespace in according pre-processor tags like e.g.
#if UNITY_EDITOR
using UnityEditor;
#endif
and the same for any code related to this namespace (see also Platform Dependent Compilation)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/435810.html
標籤:C# unity3d 统一编辑 unity3d 编辑器
