1

I'm working on a Unity 2D multiplayer game using UNet. My problem is that the Client cant send the [Command] to the server. Im debugging on UnityEditor and a built apk for my android phone.

First I used UnityEditor as Host and the phone as Client, the Debug.Log(SkinName) APPEARS on the console.

Then I used UnityEditor as the Client and the phone as Host, the Debug.Log(SkinName) DOES NOT APPEAR.

I tried to use [ClientRpc] instead of [Client] but it just made it worse, both client and host wont sync. I dont know if I excuted the [ClientRpc] in the right way.(im a noob at UNet)

I've visited other threads/forums and other UNet tutorials to look for solutions but this is what I came up with.

Note: On the other threads that I visited, people mostly suggest that Local Player Authority is unchecked and that is what causing the problem but in this case it is CHECKED.

Code:

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 ();
    }
}

}

Daniel
  • 64
  • 2
  • 14

1 Answers1

2

Ok, so from what i can see you are trying to sync the skins being used by each player so that each player has the correct skin on every client.

There are a couple of problems with your code, in both syntax and structure.

First lets look at the syntax.

You should absolutely use [ClientRpc] instead of [Client] and the method should be named RpcTransmitSkins. If the script is attached to the player prefab and Local Player Authority is Checked on the network identity then it will work. [Client] belongs to a different networking API entirely.

Now lets look at the structure.

The basic logic is correct, however, in reality the SyncSkin method will be called long before the Transmission is received.

The Start method will not wait for the transmission, so why not move the skin assignment to the Rpc, that way the other versions of the player will only try to assign their skin once the message is received.

You also have certain actions split up that all clients need to do, getting the SkeletonRenderer for example

Here is how I would restructure your script.

    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]);
            }
        }
    }

Don't be disheartened by the learning curve of the UNET system. It's super confusing to think in multi client and server terms. Even this simple action had me scratching my head for a few minutes :D

turnipinrut
  • 614
  • 4
  • 12
  • BTW, in this script should I use the [SyncVar] ? – Daniel Oct 04 '16 at 10:48
  • No, you don't need that here. The SyncVar only syncs from Server>Client, and it does it frequently. As far as i can see you just need it synced once on start. In fact, i think you can get rid of SkinName totally – turnipinrut Oct 04 '16 at 11:03
  • I tried the code and this happened, on host both player has the same look. [link]http://www.directupload.net/file/d/4498/8ca64hjj_png.htm – Daniel Oct 04 '16 at 11:15
  • ok now on host it is fine, but on client this happened. [link]http://www.directupload.net/file/d/4498/57t86fb3_png.htm. The character with blue hair should be a guy with black hair – Daniel Oct 04 '16 at 11:31
  • and it gives this error NullReferenceException: Object reference not set to an instance of an object SetupLocalPLayer.RpcTransmitSkins (System.String TransmittedSkinName) (at Assets/Scripts/SetupLocalPLayer.cs:52) – Daniel Oct 04 '16 at 11:33
  • what is at line 52 then? – turnipinrut Oct 04 '16 at 11:38
  • skeletonrenderer.skeleton.SetAttachment (SlotNames [z], TransmittedSkinName + AttachmentSuffix [z]); This is the one inside the for loop on thr Rpc – Daniel Oct 04 '16 at 11:42
  • that means that something is null. Perhaps skeletonrenderer? You will have to Debug it t find out. It's not really related to the original issue. The nCmd is sending now. – turnipinrut Oct 04 '16 at 11:44
  • Hmmm, btw Thanks for the help! I'll check on the Rpc if skeletonrenderer is null. :) . I'll mark this as answer when I finish debugging this. THANKS AGAIN! :) – Daniel Oct 04 '16 at 11:50
  • Thank you SOOO MUUCH!! now its fine on both. I just initiated the SkeletetonRenderer using the inspector. – Daniel Oct 04 '16 at 11:58
  • Wtf, run this the second time, then it suddenly doesnt work – Daniel Oct 04 '16 at 12:02
  • When I use my laptop as my host, client is not syncing :( – Daniel Oct 04 '16 at 12:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124892/discussion-between-turnipinindia-and-daniel). – turnipinrut Oct 04 '16 at 12:11