2016-10-03 101 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