2016-10-03 102 views
1

我正在使用UNet进行Unity 2D多人游戏。我的问题是,客户端不能发送[Command]到服务器。 Im在UnityEditor上进行调试,并为我的android手机构建一个apk。如何在UNet(Unity)中的客户端调用[命令]

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

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

我试图用[ClientRpc]而不是[Client]但它只是使病情加重,无论是客户端和主机不会同步。我不知道我是否以正确的方式执行了[ClientRpc](我是UNet的noob)

我访问了其他线程/论坛和其他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(); 
    } 
} 

}

+0

建议添加unet标签。 –

+0

补充说明,你可以帮我这个先生吗?它使我烦恼几天:( – Daniel

+0

我希望我可以,我已经尝试过并且失败了unet系统,这就是为什么我认为它可能会更好地为你投下一个更大的网,对不起队友 –

回答

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

+0

我会马上试试。 – Daniel

+0

顺便说一句,在这个脚本中我应该使用[SyncVar]? – Daniel

+0

不,你不需要在这里SyncVar只能从服务器>客户端同步,并且它经常使用同步,就我所见,你只需要它实际上,我认为你可以完全摆脱SkinName – turnipinrut