I am working on a network project in Unity. following code is currently working but its not optimal since I will have to write very similar code over and over again. I read about delegates, lambdas and/or command-patterns but I cant figure out how to do it. I would like to store a function to invoke it as soon as networkauthority is handed over to the client.
Following code spawns a GameObject "corner":
public void CornerSpawnRequest(Vector3 spawnPosition, GameObject joinToObject)
{
NetworkIDRequest.instance.RequestAuthority(GetComponent<NetworkIdentity>());
StartCoroutine(WaitForSeconds(spawnPosition, joinToObject));
}
IEnumerator WaitForSeconds(Vector3 spawnPosition, GameObject joinToObject)
{
yield return new WaitForSeconds(.1f);
NetworkCornerSpawn(spawnPosition, joinToObject);
}
[Command]
private void NetworkCornerSpawn(Vector3 spawnPosition, GameObject joinToObject)
{
CornerSpawnExecution(spawnPosition, joinToObject);
}
Following code is part of the player to conveniently allow handover of authority. The delegate section is not doing something at the moment but only shows what I tried:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using System;
public class NetworkIDRequest : NetworkBehaviour
{
//Singleton pattern in void Start().
//I deleted it for Stackoverflow to optimize readeability
private void Update()
{
//RunWithAuthority();
}
public delegate void taskDelegate();
private taskDelegate clickOnGameObjectDelegate = delegate { };
public taskDelegate command
{
get => clickOnGameObjectDelegate;
set => clickOnGameObjectDelegate = value;
}
public void RequestAuthority(NetworkIdentity identity)
{
CmdRequestNetworkAuthority(identity);
}
[Command]
private void CmdRequestNetworkAuthority(NetworkIdentity identity)
{
identity.AssignClientAuthority(base.connectionToClient);
}
}
I would like to replace the two lines in "CornerSpawnRequest()" with some kind of delegate in class NetworkIDRequest to always hand over a network ID that I want to request authority for and a function that shall be called as soon as I have authority. The function should have undefined amounts of attributes. Thats why I couldnt figure out a solution. I only know how to create delegates that have defined attributes.
I hope someone can tell me how to solve this problem in a solid and less clunky way. Thanks allready
best Björn
Whenever you need a delegate with unknown signature simply wrap it inside of an Action
(basically a parameter less void
delegate)
You could probably do something like
// For storing the callback
private Action _whenHaveAuthority;
// For storing the NetworkIdentity that requested authority
// In order to check back later if the event is for us
private NetworkIdentity _identity;
public void RequestAuthority(NetworkIdentity identity, Action whenHaveAuthority)
{
// Store identity and callback
_whenHaveAuthority = whenHaveAuthority;
_identity = identity;
CmdRequestNetworkAuthority(identity);
}
[Command]
private void CmdRequestNetworkAuthority(NetworkIdentity identity)
{
identity.AssignClientAuthority(base.connectionToClient);
Rpc_InformClientHasAuthority(identity);
}
// Server informs all clients
[ClientRpc]
private void Rpc_InformClientHasAuthority(NetworkIdentity identity)
{
// Check if we are the one that sent the request
if(_identity && _identity == identity)
{
// Execute the stored callback
_whenHaveAuthority?.Invoke();
// and reset
_identity = null;
_whenHaveAuthority = null;
}
}
And then you would pass in the callback like e.g.
public void CornerSpawnRequest(Vector3 spawnPosition, GameObject joinToObject)
{
NetworkIDRequest.instance.RequestAuthority(GetComponent<NetworkIdentity>(), () =>
{
NetworkCornerSpawn(spawnPosition, joinToObject);
});
}
[Command]
private void NetworkCornerSpawn(Vector3 spawnPosition, GameObject joinToObject)
{
CornerSpawnExecution(spawnPosition, joinToObject);
}
Note: Typed on smartphone but I hope the idea gets clear