버전: 2021.3+
이 예제는 직렬화된 바운드 오브젝트의 프로퍼티가 변경될 때 콜백을 수신하는 방법을 보여 줍니다.
이 예시에서는 두 개의 필드가 있는 커스텀 인스펙터를 생성합니다. 필드 값이 특정 범위를 벗어나면 사용자에게 경고가 표시됩니다.
예시의 완성된 파일은 GitHub 저장소에서 찾을 수 있습니다.
이 가이드는 Unity 에디터, UI 툴킷, C# 스크립팅에 익숙한 개발자를 위한 가이드입니다. 시작하기 전에 먼저 다음을 숙지하십시오.
C# 스크립트를 생성하여 m_BaseDamage 및 m_HardModeModifier 프로퍼티가 있는 MonoBehaviour로 Weapon 클래스를 정의합니다.
임의의 템플릿을 사용하여 Unity에서 프로젝트를 생성합니다.
프로젝트 창에서 파일을 저장할 callback-any-SerializedProperty-changes라는 폴더를 만듭니다.
Weapon.cs라는 이름의 C# 스크립트를 생성하고 해당 콘텐츠를 다음과 같이 바꿉니다.
using UnityEngine;
namespace UIToolkitExamples
{
public class Weapon : MonoBehaviour
{
public const float maxDamage = 9999f;
[SerializeField]
float m_BaseDamage;
[SerializeField]
float m_HardModeModifier;
public float GetDamage(bool hardMode)
{
return hardMode ? m_BaseDamage * m_HardModeModifier : m_BaseDamage;
}
}
}
Weapon에 대한 커스텀 인스펙터를 정의하고 TrackSerializedObjectValue() 메서드를 사용하여 m_BaseDamage 및 m_HardModeModifier 프로퍼티의 변경 사항을 확인하는 C# 스크립트를 생성합니다.
callback-any-SerializedProperty-changes 폴더에 Editor라는 폴더를 만듭니다.
Editor 폴더에서 WeaponCustomEditor.cs라는 C# 스크립트를 생성하고 해당 콘텐츠를 다음과 같이 바꿉니다.
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
namespace UIToolkitExamples
{
[CustomEditor(typeof(Weapon))]
public class WeaponCustomEditor : Editor
{
// This is text used for the warning labels.
const string k_NegativeWarningText =
"This weapon has a negative final damage on at least 1 difficulty level.";
static readonly string k_DamageCapWarningText =
"This weapon has an excessive final damage that is capped to " + Weapon.maxDamage +
" on at least 1 difficulty level.";
// These are labels to warn users about negative damage and excessive damage.
Label m_NegativeWarning, m_DamageCapWarning;
public override VisualElement CreateInspectorGUI()
{
VisualElement root = new();
// Create FloatFields for serialized properties.
var baseDamageField = new FloatField("Base Damage") { bindingPath = "m_BaseDamage" };
var modifierField = new FloatField("Hard Mode Modifier") { bindingPath = "m_HardModeModifier" };
root.Add(baseDamageField);
root.Add(modifierField);
// Create warning labels and style them so they stand out.
var warnings = new VisualElement();
m_NegativeWarning = new(k_NegativeWarningText);
m_DamageCapWarning = new(k_DamageCapWarningText);
warnings.style.color = Color.red;
warnings.style.unityFontStyleAndWeight = FontStyle.Bold;
warnings.Add(m_NegativeWarning);
warnings.Add(m_DamageCapWarning);
root.Add(warnings);
// Determine whether to show the warnings at the start.
CheckForWarnings(serializedObject);
// Whenever any serialized property on this serialized object changes its value, call CheckForWarnings.
root.TrackSerializedObjectValue(serializedObject, CheckForWarnings);
return root;
}
// Check the current values of the serialized properties to either display or hide the warnings.
void CheckForWarnings(SerializedObject serializedObject)
{
// For each possible damage values of the weapon, determine whether it's negative and whether it's above the
// maximum damage value.
var weapon = serializedObject.targetObject as Weapon;
var damages = new float[] { weapon.GetDamage(true), weapon.GetDamage(false) };
var foundNegativeDamage = false;
var foundCappedDamage = false;
foreach (var damage in damages)
{
foundNegativeDamage = foundNegativeDamage || damage < 0;
foundCappedDamage = foundCappedDamage || damage > Weapon.maxDamage;
}
// Display or hide warnings depending on the values of the damages.
m_NegativeWarning.style.display = foundNegativeDamage ? DisplayStyle.Flex : DisplayStyle.None;
m_DamageCapWarning.style.display = foundCappedDamage ? DisplayStyle.Flex : DisplayStyle.None;
}
}
}
씬에서 빈 게임 오브젝트를 만듭니다.
해당 게임 오브젝트를 선택합니다.
인스펙터에서 Weapon 컴포넌트를 추가합니다.
Weapon 컴포넌트에서 필드의 값을 다음과 같이 변경합니다.