【问题标题】:How to call [Command] on Client in UNet(Unity)如何在 UNet(Unity) 的客户端上调用 [Command]
【发布时间】:2016-10-03 20:53:31
【问题描述】:

我正在使用 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 ();
    }
}

}

【问题讨论】:

  • 建议同时添加 unet 标签。
  • 已添加,您能帮我解决这个问题吗?它困扰了我好几天:(
  • 我希望我能,我已经尝试过并且失败了 unet 系统。这就是为什么我认为你最好撒一张更大的网。对不起,伙计。

标签: c# unity3d multiplayer unity3d-unet


【解决方案1】:

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

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

首先让我们看看语法。

您绝对应该使用[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

【讨论】:

  • 顺便说一句,在这个脚本中我应该使用 [SyncVar] 吗?
  • 不,这里不需要。 SyncVar 仅从服务器>客户端同步,并且它经常这样做。据我所知,您只需要在启动时同步一次。事实上,我认为你可以完全摆脱 SkinName
  • 我尝试了代码并且发生了这种情况,在主机上两个播放器的外观相同。 [链接]directupload.net/file/d/4498/8ca64hjj_png.htm
  • 现在在主机上没问题,但在客户端发生了这种情况。 [链接]directupload.net/file/d/4498/57t86fb3_png.htm.蓝头发的角色应该是黑头发的人
  • 它给出了这个错误 NullReferenceException: Object reference not set to an instance of an object SetupLocalPLayer.RpcTransmitSkins (System.String TransmittedSkinName) (at Assets/Scripts/SetupLocalPLayer.cs:52)
猜你喜欢
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 2019-05-17
  • 2017-05-15
  • 2017-09-23
  • 2018-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多