【问题标题】:Unity Networking 2d game, ClientRpc not working correctlyUnity Networking 2d 游戏,ClientRpc 无法正常工作
【发布时间】:2019-01-15 19:26:36
【问题描述】:

我正在为我的学校项目建立一个 2d 游戏网络,但在尝试让玩家在网络场景中“进化”时遇到了问题。玩家只会在客户端而不是主机上正确进化。导致问题的代码在 Evolve 脚本的某个地方,但我不知道如何通过代码显示问题,因为问题在于代码的制定。 因此,我附上了这两个代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using UnityEngine;

public class Evolve : NetworkBehaviour {

    public bool canEvolve;
    public bool isEvolving;
    public int evoTimer;
    public int timeToEvolve;
    public int currentEvo;
    public GameObject Evo0;
    public GameObject Evo1;
    public GameObject Evo2;
    public GameObject nextEvo;
    public GameObject nextA_Atk;
    public GameObject nextB_Atk;

    // Use this for initialization

    void Start() {
        canEvolve = true;
        isEvolving = false;
        evoTimer = 0;
        timeToEvolve = GameObject.FindGameObjectWithTag("Settings").GetComponent<GameSettings>().timeToEvolve;
        currentEvo = -1;
        RpcCallEvolve();
    }

    // Update is called once per frame
    void Update() {
        if (!isLocalPlayer)
        {
            return;
        }
        if ((Input.GetButton("Evolve")) && (canEvolve == true))
        {
            isEvolving = true;
            evoTimer += 1;
            if (evoTimer >= timeToEvolve)
            {
                RpcCallEvolve();
            }
        }
        else
        {
            isEvolving = false;
            evoTimer = 0;
        }
    }

    [ClientRpc(channel = 0)]
    void RpcCallEvolve()
    {
        currentEvo += 1;
        switch (currentEvo)
        {
            case 0:
                nextEvo = Instantiate(Evo0) as GameObject;
                break;
            case 1:
                nextEvo = Instantiate(Evo1) as GameObject;
                break;
            case 2:
                nextEvo = Instantiate(Evo2) as GameObject;
                break;
            case 3:
                Win(name);
                break;
        }
        GetComponent<SpriteRenderer>().sprite = nextEvo.GetComponent<SpriteRenderer>().sprite;
        GetComponent<PolygonCollider2D>().points = nextEvo.GetComponent<PolygonCollider2D>().points;
        canEvolve = true;
        evoTimer = 0;
        Destroy(nextEvo);
    }
    void Win(string player)
    {
        Debug.Log("Winner is " + player);
        gameObject.SetActive(false);
    }
}

如果可以帮助人们找出问题,还有一个下载完整项目的链接。 https://1drv.ms/u/s!ArLjF5CAV1VwgbxZdCQkb_9PZ_j5kw

我不需要修复或整理其余代码,只需了解可能对上述问题有用的信息。

非常感谢任何提供帮助的人。

【问题讨论】:

    标签: c# unity3d network-programming unity-networking unet


    【解决方案1】:

    查看您的脚本后,似乎存在一些问题。首先,让我们回顾一下使用 ClientRPC 的一些规则:

    • 服务器/主机上调用ClientRPC,并在所有客户端上调用相应的方法(包括主机,因为主机是服务器客户端组合)
    • ClientRPC 应该在服务器上调用,否则它们将无法正常工作。 ClientRPC 可以被客户端调用,但它们不会向服务器发送任何数据,它会像普通方法一样工作。

    现在让我们看看你的脚本。您的RpcCallEvolve 方法在Update 方法中被调用,但您检查的首先 是脚本是否在本地播放器上。这引入了一些问题,主要是 RpcCallEvolve 方法只会在拥有该播放器的客户端上调用。如果这恰好在主机的播放器上被调用,那么脚本应该可以正常工作,因为无论如何都会在服务器上调用 ClientRPC。但是,如果在您的客户端上调用它,它将像常规的本地方法一样工作(正如我们前面提到的)。我建议使用命令,以确保在服务器上调用 ClientRPC。命令仅适用于播放器对象,因此请记住此 Evolve 脚本必须在播放器对象上。

    [Command]
    public void CmdServerEvolve () 
    {
        RpcCallEvolve();
    }
    

    所以不要在更新函数中调用RpcCallEvolve,而是调用CmdServerEvolve。如果有任何不清楚的地方,请随时提出问题。希望这会有所帮助!

    【讨论】:

    • 非常感谢,现在更有意义了。我不认为我之前完全理解 ClientRpc 是如何工作的,这有助于澄清很多。
    • @TheMemur UNET 上手可能会让人很困惑,如果您还有任何问题,请随时问我!
    猜你喜欢
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    相关资源
    最近更新 更多