c# - 如何在 C# 中订阅从 Unity 中的另一个实例调度的实例中的事件?

标签 c# events unity3d

假设我有一个继承自 MonoBehavior 的类,如下所示:

public interface IApplication
{
    void run();
}

public class Application : IApplication
{
    public static IServiceManager serviceManager;
    public delegate void ApplicationStartedEvent(object source, EventArgs args);
    public event ApplicationStartedEvent applicationStartedEvent;

    public void run()
    {

    }

    protected virtual void OnApplicationStarted()
    {
        if (applicationStartedEvent != null)
        {
            applicationStartedEvent(this, EventArgs.Empty);
        }
    }
}

还有一个像这样的 MonoBehavior 的 Unity Controller :

public class LoginController : MonoBehaviour 
{
    void Start()
    {
        Hide();
    }

    public void OnApplicationStarted(object source, EventArgs e)
    {
        Show();
    }

    public virtual void Show()
    {
        gameObject.SetActive(true);
    }

    public virtual void Hide()
    {
        gameObject.SetActive(false);
    }
}

如何将这两者联系起来?

假设我有以下 Bootstrap 代码:

public class Setup : MonoBehaviour
{
    Application application;

    void Awake()
    {
        application = new Application();
        application.run();
    }
}

如何在 Application run 方法被调用时运行我的 LoginController OnApplicationStarted 方法或调度 ApplicationStartedEvent 的事件。

我认为 EventManager 应该是什么样子的示例:

addEventListener(string eventName, Callback 回调)

dispatchEvent(事件事件)

下面是如何在 LoginController 中使用它:

EventManager.addEventListener("ApplicationStarted", this.OnApplicationStarted)

下面是如何在应用程序中使用它:

public void run()
{
    EventManager.dispatchEvent(new ApplicationStartedEvent());
}

显然这只是一个想法,不必使用相同的语法。

编辑: 我想我找到了与我正在寻找的几乎相似的东西: http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger

最佳答案

How do I make my LoginController OnApplicationStarted method run when Application run method is being invoked or Dispatch an event that is ApplicationStartedEvent.

创建一个可以注册和取消注册事件的EventManager 脚本。此函数应将 ApplicationStartedEvent 作为参数。再添加一个可用于调用订阅事件的函数。

然后您可以订阅来自其他脚本的事件,例如 LoginController 脚本。订阅应该在 OnEnableOnDisable 函数中完成。

然后可以从应用程序脚本中的 run() 函数调用事件。

非常重要:

请将您的Application 脚本重命名为Application2 或其他名称。有一个名为 Application 的 Unity API如果您使用此类中的函数,您将遇到编译时错误。

在此解决方案中,我将使用 Application2 而不是 Application

EventManager.cs:

请将其附加到一个空的游戏对象

public class EventManager : MonoBehaviour
{
    private static EventManager localInstance;
    public static EventManager Instance { get { return localInstance; } }

    private void Awake()
    {
        if (localInstance != null && localInstance != this)
        {
            Destroy(this.gameObject);
        }
        else
        {
            localInstance = this;
        }
    }

    public delegate void ApplicationStartedEvent(object source, EventArgs args);
    private event ApplicationStartedEvent applicationStartedEvent;


    public void dispatchEvent(object source, EventArgs args)
    {
        foreach (ApplicationStartedEvent runEvent in applicationStartedEvent.GetInvocationList())
        {
            try
            {
                runEvent.Invoke(source, args);
            }
            catch (Exception e)
            {
                Debug.LogError(string.Format("Exception while invoking" + runEvent.Method.Name + e.Message));
            }
        }
    }

    public void registerEvent(ApplicationStartedEvent callBackFunc)
    {
        applicationStartedEvent += callBackFunc;
    }

    public void unRegisterEvent(ApplicationStartedEvent callBackFunc)
    {
        applicationStartedEvent -= callBackFunc;
    }
}

Application2.cs:

public class Application2 : IApplication
{
    public void run()
    {
        OnApplicationStarted();
    }

    protected virtual void OnApplicationStarted()
    {
        EventManager.Instance.dispatchEvent(this, EventArgs.Empty);
    }
}

LoginController.cs:

public class LoginController : MonoBehaviour
{

    void Start()
    {
        Hide();
    }

    public void OnApplicationStarted(object source, EventArgs e)
    {
        Show();
    }

    public virtual void Show()
    {
        gameObject.SetActive(true);
    }

    public virtual void Hide()
    {
        gameObject.SetActive(false);
    }

    void OnEnable()
    {
        //Subscribe to event
        EventManager.Instance.registerEvent(OnApplicationStarted);
    }

    void OnDisable()
    {
        //Un-Subscribe to event
        EventManager.Instance.unRegisterEvent(OnApplicationStarted);
    }
}

关于c# - 如何在 C# 中订阅从 Unity 中的另一个实例调度的实例中的事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41159075/

相关文章:

c# - 如果太多用户使用 c# 使用 asp.net 在 sql 中访问该表,则更新表的最佳方法

c# - ViewModel 是否应该公开诸如 BitmapImage 或 ImageSource 或音频文件缓冲区之类的东西?

php - Symfony 事件订阅者对调度没有反应

php - 如何在 magento 结帐过程之前设置自定义总计?

c# - unity 更新运动向量。矢量值的物理意义

c# - 生成程序平铺背景

c# - IIS Express 和 IIS 中功能锁和互斥量的使用行为不同

c# - 使用 C# 写入现有的 Excel 文件

c# - 创建一个跨进程的 EventWaitHandle

unity3d - 在 Unity 中获取实时 HTC Vive Controller 位置