【问题标题】:Store function for later use / delegate with undefined attributes存储功能以供以后使用/委托未定义的属性
【发布时间】:2020-12-30 11:38:55
【问题描述】:

我正在使用 Unity 开发一个网络项目。以下代码目前正在运行,但不是最优的,因为我将不得不一遍又一遍地编写非常相似的代码。我阅读了有关委托、lambda 和/或命令模式的信息,但我不知道该怎么做。 我想存储一个函数,以便在将网络权限移交给客户端后立即调用它。

以下代码生成一个游戏对象“角”:

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);
}

以下代码是播放器的一部分,可方便地进行权限移交。 代表部分目前没有做任何事情,但只显示了我尝试过的内容:

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);
    }
}

我想将“CornerSpawnRequest()”中的两行替换为 NetworkIDRequest 类中的某种委托,以始终交出我想要请求权限的网络 ID 和应在我完成后立即调用的函数有权威。该函数应具有未定义数量的属性。这就是为什么我想不出一个解决方案。我只知道如何创建已定义属性的委托。

我希望有人能告诉我如何以可靠且不那么笨拙的方式解决这个问题。 已经谢谢了

最好的 比约恩

【问题讨论】:

    标签: c# unity3d lambda delegates


    【解决方案1】:

    当您需要一个签名未知的委托时,只需将其包装在 Action 内(基本上是一个参数较少的 void 委托)

    你可能会做类似的事情

    // 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;
        }
    }
    

    然后你会传入回调,例如

    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);
    }
    

    注意:在智能手机上输入,但我希望思路清晰

    【讨论】:

    • 这太棒了!也感谢您的速度非常快;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多