Я бы также предложил использовать события, но будьте осторожны, как и когда вы регистрируете и удаляете слушателей!
public class A : ScriptableObject
{
// You don't need [SerializeField]
// public properties are serialized anyway
public string team;
public event Action onChanged;
public event Action onReset;
public event Action onDestroyed;
private void OnValidate()
{
Debug.Log($"My team name has been changed to {team}.");
if(onChanged == null) return;
onChanged.Invoke();
}
// This is called on reset
// But if you override this you have to set
// The default values yourself!
private void Reset()
{
team = "";
if (onReset == null) return;
onReset.Invoke();
}
// Called when object is destroyed
private void OnDestroyed()
{
if(onDestroyed == null) return;
onDestroyed.Invoke();
}
}
Но теперь в B
я бы не добавил слушателя на Awake
, так как это добавляетэто после каждой перекомпиляции и несколько раз!Вместо этого не забудьте «очистить» всех слушателей, которых вы когда-либо добавляли, чтобы избежать получения NullReferenceExceptions:
public class B : ScriptableObject
{
// You don't need [SerializeField] since public properties
// are serialized anyway
public A a;
// Internal for removing listeners later
private A lastA;
private void OnValidate()
{
// Apparently something else was changed
if(a == lastA) return;
Debug.Log("reference a changed");
// Unregister listeners for old A reference
if(lastA)
{
lastA.onChanged -= OnAChanged;
lastA.onReset -= OnAReset;
lastA.onDestroyed -= OnADestroyed;
}
// Register listeners for new A reference
// Note that it is allways possible to remove listeners first
// even if they are not there yet
// that makes sure you listen only once and don't add multiple calls
if(a)
{
a.onChanged -= OnAChanged;
a.onReset -= OnAReset;
a.onDestroyed -= OnADestroyed;
a.onChanged += OnAChanged;
a.onReset += OnAReset;
a.onDestroyed += OnADestroyed;
}
lastA = a;
}
// Make allways sure you also remove all listeners on destroy to not get Null reference exceptions
// Note that it is allways possible to remove listeners even if they are not there yet
private void OnDestroy()
{
if(!a) return;
a.onChanged -= OnAChanged;
a.onReset -= OnAReset;
a.onDestroyed -= OnADestroyed;
}
private void OnAChanged()
{
Debug.Log("A was changed");
}
private void OnAReset()
{
Debug.Log("A was reset");
}
private void OnADestroyed()
{
Debug.Log("a was destroyed");
}
}
Небольшое необязательное изменение, если вы хотите
Если вы хотите, чтобыВы можете зарегистрировать других слушателей в инспекторе так же, как вы делаете для Button
s, вы можете просто поменять
public event Action xy;
на
public UnityEvent xy;
и удалить проверки if(xy == null)
.
Вы бы также заменили
a.onChanged -= OnAChanged;
a.onChanged += OnAChanged;
на
a.onChanged.RemoveListener(OnAChanged);
a.onChanged.AddListener(OnAChanged);