如何在UNet(Unity)

时间:2016-10-03 20:53:32

标签: c# unity3d multiplayer unity3d-unet

我正在使用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教程以寻找解决方案,但这就是我想出来的。

注意:在我访问过的其他主题中,人们主要建议取消选中Local Player Authority,这就是造成问题的原因,但在这种情况下它是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 ();
    }
}

}

1 个答案:

答案 0 :(得分: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