I'm trying to understand my question. I have a server object in Unity scene. The server needs to invoke different methods from different scenes each time a message from Client arrives.
I'd prefer not to keep references to all the interaction scripts in my scene within the Server script. My solution was to create a delegate and have the interaction script subscribe to the delegate event. However my scene has changed and I find that two methods from different scripts subscribe to the same delegate and I get only on good outcome.
My solution was to create another delegate specifically to the next method but I wonder how many delegates can I create and is there a way to create one delegate but have it execute another function each time (or is it another action?)
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();
}
I want if its possible to have one delegate OnCommunication(), and have different scripts subscribe to it to execute their unique methods and not execute the method from the previous script that in the scene.
Is it possible and what work flow would you suggest?
I don't fully understand the question yet and don't see where you subscripe the callbacks to the events.
I wonder how many delegates can I create
→ As many as you like! The question is do you need and do you want to?
If you want to add multiple callbacks to one event (that's how the title sounds) you simply use +=
instead of =
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);
}
}
If your question is rather like "I want to add multiple callbacks but execute always only one of them." I would suggest to not use event
s at all but something like
public interface IServerCommunicationHandler
{
void OnServerCommunication();
}
public interface IServerSceneSyncHandler
{
void OnServerSceneSync();
}
And in the server store listeners like
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);
}
}
and than instead of OnCommunication?Invoke()
and OnSceneSync?.Invoke()
have e.g.
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);
}
Then the scripts could look like e.g.
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);
}
}