Вероятно, есть много способов сделать это.
Публичный статический список
public class A : MonoBehaviour
{
public static List<A> AvailableAs = new List<A>();
private void Awake()
{
if(!AvailableAs.Contains(this)) AvailableAs.Add(this);
}
private void OnDestroy()
{
if(AvailableAs.Contains(this)) AvailableAs.Remove(this);
}
public void SomePublicMethod()
{
// magic
}
}
и используйте его, например. как
public class B : MonoBehaviour
{
// run the method on all currently registered A instances
public void DoIt()
{
foreach(var a in A.AvailableAs)
{
a.SomePublicMethod();
}
}
}
Global EventHandler
Или, если вы предпочитаете инкапсуляцию, используйте, как вы упомянули, глобальный обработчик событий для всех A, например
namespace ANamespace
{
public static class AEventHandler
{
internal static event Action OnInvokeA;
public static void InvokeAEvent()
{
if(OnInvokeA != null) OnInvokeA.Invoke();
}
}
}
и в A есть
namespace ANamespace
{
public class A : MonoBehaviour {
private void Awake()
{
// it is save to remove a callback first even
// if it was not added yet. This makes sure it is
// added only once always
AEventHandler.OnIvokeA -= SomePrivateMethod;
AEventHandler.OnIvokeA += SomePrivateMethod;
}
private void OnDestroy()
{
AEventHandler.OnIvokeA -= SomePrivateMethod;
}
private void SomePrivateMethod()
{
// magic
}
}
}
Теперь в B
вы бы просто сделали
// invoke the event and whoever is added as listener will do
// whatever he registered
// in this case all A instances execute their method
AEventHandler.InvokeAEvent();
Событие единства
Если у вас есть только один класс A
, который генерирует событие, и вы хотите, чтобы другие реагировали на него, просто используйте UnityEvent
как
public class A : MonoBehaviour
{
public UnityEvent OnSomethingHappened = new UnityEvent();
private void SomeMethodIWillRun()
{
//...
OnSomethingHappened.Invoke();
}
}
Теперь вы не можете легко добавлять обратные вызовы к этому событию в Инспекторе Unity, перетаскивая в GameObjects / Components и выбирая метод для вызова. (Точно то же самое используется для события onClick
компонента Button
, кстати;))
И вы все еще можете добавлять обратные вызовы через скрипт во время выполнения, как
public class B : MonoBehaviour
{
public A referenceToA;
private void Start()
{
referenceToA.OnSomethingHappened.AddCallback(OnASomethingHappened);
}
private void OnDestroy()
{
referenceToA.OnSomethingHappened.RemoveCallback(OnASomethingHappened)
}
private void OnASomethingHappened()
{
//
}
}
Примечание: напечатано на смартфоне, поэтому никаких гарантий, но я надеюсь, что идея проясняется.