1

我正在使用 UNet 开发 Unity 2D 多人游戏。我的问题是客户端无法将其发送[Command]到服务器。我在 UnityEditor 上调试,并为我的 android 手机构建了一个 apk。

首先我使用 UnityEditor 作为主机,手机作为客户端,Debug.Log(SkinName) APPEARS on the console.

然后我使用 UnityEditor 作为客户端,手机作为主机,Debug.Log(SkinName) DOES NOT APPEAR.

我尝试使用[ClientRpc]而不是,[Client]但它只会让情况变得更糟,客户端和主机都不会同步。我不知道我是否以正确的方式执行了 [ClientRpc]。(我是 UNet 的菜鸟)

我访问了其他线程/论坛和其他 UNet 教程来寻找解决方案,但这就是我想出的。

注意:在我访问的其他线程上,人们大多建议未选中本地玩家权限,这就是导致问题的原因,但在这种情况下是CHECKED.

代码:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using Spine;
using Spine.Unity;
using Spine.Unity.Modules;

class SetupLocalPLayer : NetworkBehaviour {
[SyncVar]
public string SkinName;

public string[] CharNames;
public string[] SlotNames;
public string[] AttachmentSuffix;

void Start (){
    TransmitSkins ();
    SyncSkin ();
    if (isLocalPlayer) {
        var skeletonrenderer = GetComponent<SkeletonRenderer>();
        for(int z=0;z<SlotNames.Length;z++){
            skeletonrenderer.skeleton.SetAttachment(SlotNames[z],GameController.control.skinName+AttachmentSuffix[z]);
        }
        GetComponent<PlayerManager> ().enabled = true;
        GetComponent<FollowCam> ().enabled = true;
    }
}
void Update () {

}

void SyncSkin(){
    if (!isLocalPlayer) {
        var skeletonrenderer = GetComponent<SkeletonRenderer>();
        for(int z=0;z<SlotNames.Length;z++){
            skeletonrenderer.skeleton.SetAttachment(SlotNames[z],SkinName+AttachmentSuffix[z]);
        }
    }
}

[Command]
void CmdSetSkin(){
    SkinName = GameController.control.skinName;
    Debug.Log (SkinName);
}

[Client]
void TransmitSkins(){
    if (isLocalPlayer) {
        CmdSetSkin ();
    }
}

}

4

1 回答 1

2

好的,所以据我所知,您正在尝试同步每个玩家正在使用的皮肤,以便每个玩家在每个客户端上都有正确的皮肤。

您的代码在语法和结构上都存在一些问题。

首先让我们看一下语法。

您绝对应该使用[ClientRpc]而不是,[Client]并且该方法应该命名为RpcTransmitSkins. 如果脚本附加到播放器预制件并且在网络身份上检查了本地播放器权限,那么它将起作用。[Client]完全属于不同的网络 API。

现在让我们看看结构。

基本逻辑是正确的,但实际上 SyncSkin 方法会在接收到传输之前很久就被调用。

Start方法不会等待传输,所以为什么不将皮肤分配移动到Rpc,这样其他版本的玩家只会在收到消息后尝试分配他们的皮肤。

您还可以拆分所有客户端需要执行的某些操作,例如获取 SkeletonRenderer

以下是我将如何重组您的脚本。

    void Start (){
        //first, grab the SkeletonRenderer on every version of the player. 
        //note that it should not be a local var now, but a field in the script
        skeletonrenderer = GetComponent<SkeletonRenderer>();

        //now do the local player specific stuff
        if (isLocalPlayer) {

            //transmit the skin name to the other versions of the player
            CmdSendSkinRpc(GameController.control.skinName);

            //then assign the skin to the local version of the player
            for(int z=0;z<SlotNames.Length;z++){
                skeletonrenderer.skeleton.SetAttachment(SlotNames[z],GameController.control.skinName+AttachmentSuffix[z]);
            }
            GetComponent<PlayerManager> ().enabled = true;
            GetComponent<FollowCam> ().enabled = true;
        }
    }

    [Command]
    void CmdSendSkinRpc(string skin){
        RpcTransmitSkins(skin);
        Debug.Log("Transmitting Skin Named: " + skin);
    }

    [ClientRpc]
    void RpcTransmitSkins(string TransmittedSkinName){
        if (!isLocalPlayer) {
            Debug.Log("Receiving Skin Named: " + TransmittedSkinName);
            for(int z=0;z<SlotNames.Length;z++){
                skeletonrenderer.skeleton.SetAttachment(SlotNames[z],TransmittedSkinName+AttachmentSuffix[z]);
            }
        }
    }

不要因 UNET 系统的学习曲线而灰心。用多客户端和服务器术语来思考是非常令人困惑的。即使是这个简单的动作也让我挠了几分钟:D

于 2016-10-04T10:33:28.197 回答