Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

UNet vs legacy. How to send an RPC to all players (including host)?

Discussion in 'UNet' started by Dudledok, Jul 15, 2015.

  1. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    In the legacy system if I wanted a player to let all other players know about something I could send an RPC with the mode being all so that even the sender will receive the call.

    How do I do this in UNet?

    -------------------------------------------------------------------------

    Alternative solution: Send a command to the host from the client.
    Here I have a different issue:
    • I am able to send RPCs from the host to the client
    • I am unable to send Commands to the host from the client

    My situation:
    • I have a two player game with one host and one client
    • The game has no 'players' as such because you don't have characters which you move etc
    • The game is perhaps more applicable to a turn based card game (but you have no health or similar)
    • I have a NetworkBehaviour and NetworkIdentity attached to a separate GameObject in the scene from the start of the game
    • I am using the NetworkBehaviour successfully to send RPCs from the host to the client
    • Commands in the same script can be called by the client but are not called on the server (breakpoints aren't hit)
    In the manual it says "Commands are sent from player objects on the client to player objects on the server" but I don't know what a 'player object' is or if that's even the issue I have or not.

    Hopefully someone can clear this up for me.
     
    Last edited: Jul 15, 2015
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Create a "player" object and use it for communication. The player doesn't have to be a visible model.
     
  3. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    Right, but what is a player object? The documentation doesn't quite make that clear and it almost seems like my NetworkBehaviour should simply be names Player?
     
  4. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    A player is just any gameObject with a NetworkIdentity. It is not really a type of object, just how that object is used.
     
  5. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    Okay that makes sense, but it actually already has a NetworkIdentity component attached!
    The Commands and RPCs are in a script I have created which inherits from NetworkBehaviour which is attached to a GameObject in the scene which also has a NetworkIdentity component but nothing else.
    The GameObject which has this script attached is added as a public variable in another script (and set in the inspector) so that this other script can call the RPCs and Commands by reference.
     
  6. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
  7. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
  8. Piflik

    Piflik

    Joined:
    Sep 11, 2011
    Posts:
    289
    You need an object with 'Local authority'. This object can then send 'Commands' to the server and the server can broadcast the information via RPCs or SyncVars.
     
  9. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    The "Local Player Authority" checkbox is ticked already.

    The "Auto Create Player" checkbox under "Spawn Info" is unchecked as I am not spawning any players but there is just the one which exists in the scene before running.

    To clarify, this is my entire NetworkManager script:
    Code (CSharp):
    1. public class DSMNet : NetworkManager
    2. {
    3.     public GameObject networkController;
    4.    
    5.     // called when a client connects
    6.     public override void OnServerConnect(NetworkConnection conn)
    7.     {
    8.         networkController.SetActive(true);
    9.     }
    10. }
    `networkController` is the GameObject mentioned above which has the script which inherits from NetworkBehaviour and NetworkIdentity component.
     
  10. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    But there is only one networkController object? What happens when there are multpile players?
     
    Dudledok likes this.
  11. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    I tried using more than one but clearly didn't do that right. What I don't understand is that both the server and client can call functions on that GameObject but only one can receive?
    If I duplicated that GameObject, how would I specify which is the server and which is the client? (The game is just 1v1 for now)
    Also, I have seen examples of scripts around online that people use which have both Commands and RPCs so why is that not possible here?
    The reason I did it this way is I'm used to the legacy system and wanted basically one central point which anything can use to send messages.
     
  12. robo orlo

    robo orlo

    Joined:
    Mar 19, 2015
    Posts:
    4
    If all you are doing is sending messages, I had some success using the Send functions of NetworkServer.

    http://docs.unity3d.com/ScriptReference/Networking.NetworkServer.html

    you can create a type of message on the server side, register a handler for that message type on the client, and use that to send messages.

    Server side:
    Code (CSharp):
    1. public static short MSG_MESSAGETOSEND = 54;
    2.  
    3.     public class MessageClass : MessageBase
    4.     {
    5.         public string messageToSend;
    6.     }
    7.  
    8.     public static void sendMessage(string message)
    9.     {
    10.         MessageClass msg = new MessageClass();
    11.         msg.messageToSend = message;
    12.         NetworkServer.SendToAll(msg);
    13.     }
    14.  
    15.  
    Client Side:
    Code (CSharp):
    1. public static short MSG_MESSAGETOSEND = 54;
    2. static NetworkClient netClient = new NetworkClient();
    3.  
    4.     public class MessageClass : MessageBase
    5.     {
    6.         public string messageToSend;
    7.     }
    8.  
    9. //Network Clients connect to the server
    10. netClient.RegisterHandler(MSG_MESSAGETOSEND, OnSomeMessageReceived);
    11.  
    12. public void OnSomeMessageReceived(NetworkMessage netMsg)
    13.     {
    14.         MessageClass msg = new MessageClass();
    15.         msg = netMsg.ReadMessage<MessageClass>();
    16.         foo(msg.messageToSend); //Where foo does something with the incoming message.
    17.     }
    of course, if you are doing things beyond sending a message, RPC's and Commands are likely the way to go.
     
  13. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    Yeah I don't think messages are the right way to go for sending data across the network.
     
  14. Disastorm

    Disastorm

    Joined:
    Jun 16, 2013
    Posts:
    132
    I'm not sure why you can't send commands to the server, but provided you get that working, you could do something like the following:

    [ClientRpc]
    void RpcDoStuff(){
    DoStuff();
    }

    [Command]
    void CmdDoStuff(){
    if(isLocalPlayer)return;
    RpcDoStuff();
    }

    void DoStuff(){

    }

    Update(){
    if(isLocalPlayer){
    CmdDoStuff();
    }
    }



    I believe what this should do is the local player will send CmdDoStuff to server, but will not run the method yet due to the if statement in CmdDoStuff.
    The server will then call the Rpc which will then send to all of the clients including the original sender who will then execute the DoStuff code.
    You can also move the if(isLocalPlayer) part into the RPC if you want it to execute in realtime on the client without waiting for the server.
     
  15. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110
    The problem was that the command was not running on the local player. Maybe there should be a warning for if you are trying to send commands from a player that isn't yours, even though when worded like that it should be obvious. I also changed it so that the NetworkManager automatically spawns the player prefab. Letting that do its own thing is the easiest way for sure.
    Thanks @seanr for the assistance.
     
  16. labuto

    labuto

    Joined:
    Feb 8, 2014
    Posts:
    1
    your code does not work!!!! what is MessageBase here?
     
  17. Dudledok

    Dudledok

    Joined:
    Oct 24, 2013
    Posts:
    110