如何从一个代表调用不同的 methods/scripts?
How to invoke different methods/scripts from one delegate?
我正在尝试理解我的问题。
我在 Unity 场景中有一个服务器对象。
Client的消息每次到达时,服务端需要从不同的场景调用不同的方法。
我不想在服务器脚本中保留对场景中所有交互脚本的引用。我的解决方案是创建一个委托并让交互脚本订阅委托事件。然而,我的场景发生了变化,我发现来自不同脚本的两种方法订阅了同一个委托,而且我只得到了好的结果。
我的解决方案是专门为下一个方法创建另一个委托,但我想知道我可以创建多少个委托,有没有一种方法可以创建一个委托,但每次都让它执行另一个函数(或者它是另一个动作? )
public class Server : MonoBehaviour
{
public delegate void CommunicationEvent();
public static event CommunicationEvent OnCommunication;
public delegate void PortalEvent();
public static event PortalEvent OnSceneSync;
private const int MAX_USER = 1;
private const int PORT = 26000;
private const int WEB_PORT = 26001;
private const int BYTE_SIZE = 1024;
/*.... */
private void LightsOn(int cnnId, int recHostId, Net_OnEnterGate oeg)
{
OnCommunication?.Invoke();
SendClient(recHostId, cnnId, oeg);
}
private void SceneSyncing(int cnnId, int recHostId, Net_OnSceneSync oss)
{
oss.TransNumber = LoadScene.currentSceneNumber;
OnSceneSync?.Invoke();
SendClient(cnnId, recHostId, oss);
}
private void LoadNewScene(int cnnID, int recHostId, Net_OnSceneLoad osl)
{
OnCommunication?.Invoke();
}
我希望有一个委托 OnCommunication(),并让不同的脚本订阅它以执行它们独特的方法,而不是执行场景中前一个脚本的方法。
是否可行?您建议采用哪种工作流程?
我还没有完全理解这个问题,也没有看到你在哪里订阅事件的回调。
I wonder how many delegates can I create
→喜欢多少都行!问题是你需要和想要吗?
如果你想为一个事件添加多个回调(这就是标题的发音)你只需使用 +=
而不是 =
public class Example : MonoBehaviour
{
private void Awake()
{
// Note: It is always save to remove callbacks
// even if not added yet.
// This makes sure they are added only once for this instance
OnCommunication -= OnServerCommunication;
OnSceneSync -= OnServerSceneSync;
OnCommunication += OnServerCommunication;
OnSceneSync += OnServerSceneSync;
}
privtae void OnDestroy()
{
// Make sure to always remove callbacks when not needed anymore
OnCommunication -= OnServerCommunication;
OnSceneSync -= OnServerSceneSync;
}
private void OnServerCommunication()
{
Debug.Log("Communication was invoked", this);
}
private void OnServerSceneSync()
{
Debug.Log("Scene sync was invoked", this);
}
}
如果您的问题类似于 "I want to add multiple callbacks but execute always only one of them.",我建议您完全不要使用 event
,而是使用
public interface IServerCommunicationHandler
{
void OnServerCommunication();
}
public interface IServerSceneSyncHandler
{
void OnServerSceneSync();
}
并且在服务器存储听众喜欢
public class Server : MonoBehaviour
{
private static readonly List<IServerCommunicationHandler> CommunicationListeners = new List<IServerCommunicationHandler>();
private static readonly List<IServerSceneSyncHandler> SceneSyncListeners = new List<IServerSceneSyncHandler>();
public static void AddCommunicationListener(IServerCommunicationHandler listener)
{
if (!CommunicationListeners.Contains(listener)) CommunicationListeners.Add(listener);
}
public static void RemoveCommunicationListener(IServerCommunicationHandler listener)
{
if (CommunicationListeners.Contains(listener)) CommunicationListeners.Remove(listener);
}
public static void AddSceneSyncListener(IServerSceneSyncHandler listener)
{
if (!SceneSyncListeners.Contains(listener)) SceneSyncListeners.Add(listener);
}
public static void RemoveSceneSyncListener(IServerSceneSyncHandler listener)
{
if (SceneSyncListeners.Contains(listener)) SceneSyncListeners.Remove(listener);
}
}
而不是 OnCommunication?Invoke()
和 OnSceneSync?.Invoke()
有例如
private void InvokeCommunication()
{
var listener = CommunicationListeners.Count > 0 ? CommunicationListeners[0] : null;
if (listener == null) return;
listener.OnServerCommunication();
CommunicationListeners.RemoveAt(0);
}
private void InvokeSceneSync()
{
var listener = SceneSyncListeners.Count > 0 ? SceneSyncListeners[0] : null;
if (listener == null) return;
listener.OnServerSceneSync();
SceneSyncListeners.RemoveAt(0);
}
然后脚本可能看起来像
public class Example : MonoBehaviour, IServerCommunicationHandler, IServerSceneSyncHandler
{
private void Awake()
{
Server.AddCommunicationListener(this);
Server.AddSceneSyncListener(this);
}
private void OnDestroy()
{
Server.RemoveCommunicationListener(this);
Server.RemoveSceneSyncListener(this);
}
public void OnSeverCommunication()
{
Debug.Log("Communication was invoked", this);
}
public void OnServerSceneSync()
{
Debug.Log("Scene sync was invoked", this);
}
}
我正在尝试理解我的问题。 我在 Unity 场景中有一个服务器对象。 Client的消息每次到达时,服务端需要从不同的场景调用不同的方法。
我不想在服务器脚本中保留对场景中所有交互脚本的引用。我的解决方案是创建一个委托并让交互脚本订阅委托事件。然而,我的场景发生了变化,我发现来自不同脚本的两种方法订阅了同一个委托,而且我只得到了好的结果。
我的解决方案是专门为下一个方法创建另一个委托,但我想知道我可以创建多少个委托,有没有一种方法可以创建一个委托,但每次都让它执行另一个函数(或者它是另一个动作? )
public class Server : MonoBehaviour
{
public delegate void CommunicationEvent();
public static event CommunicationEvent OnCommunication;
public delegate void PortalEvent();
public static event PortalEvent OnSceneSync;
private const int MAX_USER = 1;
private const int PORT = 26000;
private const int WEB_PORT = 26001;
private const int BYTE_SIZE = 1024;
/*.... */
private void LightsOn(int cnnId, int recHostId, Net_OnEnterGate oeg)
{
OnCommunication?.Invoke();
SendClient(recHostId, cnnId, oeg);
}
private void SceneSyncing(int cnnId, int recHostId, Net_OnSceneSync oss)
{
oss.TransNumber = LoadScene.currentSceneNumber;
OnSceneSync?.Invoke();
SendClient(cnnId, recHostId, oss);
}
private void LoadNewScene(int cnnID, int recHostId, Net_OnSceneLoad osl)
{
OnCommunication?.Invoke();
}
我希望有一个委托 OnCommunication(),并让不同的脚本订阅它以执行它们独特的方法,而不是执行场景中前一个脚本的方法。
是否可行?您建议采用哪种工作流程?
我还没有完全理解这个问题,也没有看到你在哪里订阅事件的回调。
I wonder how many delegates can I create
→喜欢多少都行!问题是你需要和想要吗?
如果你想为一个事件添加多个回调(这就是标题的发音)你只需使用 +=
而不是 =
public class Example : MonoBehaviour
{
private void Awake()
{
// Note: It is always save to remove callbacks
// even if not added yet.
// This makes sure they are added only once for this instance
OnCommunication -= OnServerCommunication;
OnSceneSync -= OnServerSceneSync;
OnCommunication += OnServerCommunication;
OnSceneSync += OnServerSceneSync;
}
privtae void OnDestroy()
{
// Make sure to always remove callbacks when not needed anymore
OnCommunication -= OnServerCommunication;
OnSceneSync -= OnServerSceneSync;
}
private void OnServerCommunication()
{
Debug.Log("Communication was invoked", this);
}
private void OnServerSceneSync()
{
Debug.Log("Scene sync was invoked", this);
}
}
如果您的问题类似于 "I want to add multiple callbacks but execute always only one of them.",我建议您完全不要使用 event
,而是使用
public interface IServerCommunicationHandler
{
void OnServerCommunication();
}
public interface IServerSceneSyncHandler
{
void OnServerSceneSync();
}
并且在服务器存储听众喜欢
public class Server : MonoBehaviour
{
private static readonly List<IServerCommunicationHandler> CommunicationListeners = new List<IServerCommunicationHandler>();
private static readonly List<IServerSceneSyncHandler> SceneSyncListeners = new List<IServerSceneSyncHandler>();
public static void AddCommunicationListener(IServerCommunicationHandler listener)
{
if (!CommunicationListeners.Contains(listener)) CommunicationListeners.Add(listener);
}
public static void RemoveCommunicationListener(IServerCommunicationHandler listener)
{
if (CommunicationListeners.Contains(listener)) CommunicationListeners.Remove(listener);
}
public static void AddSceneSyncListener(IServerSceneSyncHandler listener)
{
if (!SceneSyncListeners.Contains(listener)) SceneSyncListeners.Add(listener);
}
public static void RemoveSceneSyncListener(IServerSceneSyncHandler listener)
{
if (SceneSyncListeners.Contains(listener)) SceneSyncListeners.Remove(listener);
}
}
而不是 OnCommunication?Invoke()
和 OnSceneSync?.Invoke()
有例如
private void InvokeCommunication()
{
var listener = CommunicationListeners.Count > 0 ? CommunicationListeners[0] : null;
if (listener == null) return;
listener.OnServerCommunication();
CommunicationListeners.RemoveAt(0);
}
private void InvokeSceneSync()
{
var listener = SceneSyncListeners.Count > 0 ? SceneSyncListeners[0] : null;
if (listener == null) return;
listener.OnServerSceneSync();
SceneSyncListeners.RemoveAt(0);
}
然后脚本可能看起来像
public class Example : MonoBehaviour, IServerCommunicationHandler, IServerSceneSyncHandler
{
private void Awake()
{
Server.AddCommunicationListener(this);
Server.AddSceneSyncListener(this);
}
private void OnDestroy()
{
Server.RemoveCommunicationListener(this);
Server.RemoveSceneSyncListener(this);
}
public void OnSeverCommunication()
{
Debug.Log("Communication was invoked", this);
}
public void OnServerSceneSync()
{
Debug.Log("Scene sync was invoked", this);
}
}