Search Unity

Order of Methods? Creating Custom Spawning

Discussion in 'Multiplayer' started by DRRosen3, Feb 16, 2016.

  1. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    So I'm trying to dig deeper into UNet, but I think my understanding of what happens when a player connects to a host/server (via MatchMaker) is a bit off. I know the following order:
    1. singleton.matchMaker.JoinMatch()
    2. singleton.OnMatchJoined()
    3. singleton.StartClient()
    4. ???
    I don't know what comes next. Basically I'm trying to learn how to write my own process for connecting to the host/server. What I need to accomplish is:
    1. Player signs in. (I've done this using WWWForms, PHP, and MySQL)
    2. Player switches to online scene.
    3. Player prefab should NOT auto-spawn because I need to populate variable values from the database.
    4. Once the values (name, stats, last position etc) are populated, player is spawned AT the last position.
    I client holds the key to "downloading" the data from the database...it's character's name. The NetworkManager has a string variable to hold the character's name. When the player logs in (successfully) their NetworkManager's (I wrote a custom one deriving from Unity's NetworkManager) variable becomes equal to the character name pulled from the database belonging to that user. After that the scene changes to the online scene. I need to then start the process of creating the player, but I don't want to actually SPAWN the player until I finish downloading its data from the database, on the server and populating its values. Only thing is, in order for the server to know where to get the data from, I have to pass the string of the character's name from the clients NetworkManager, to the server.
     
    Deleted User likes this.
  2. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Nobody?
     
  3. Zero123

    Zero123

    Joined:
    Aug 31, 2014
    Posts:
    23
    Bump i am also interested in this info
     
  4. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Oh come on. Would somebody from Unity please answer this question so I (and apparently others) can move forward? I think I have a good idea of the order but I want to be sure.
    1. Client calls OnMatchJoined() when they successfully join a match.
    2. Client calls StartClient().
    3. Client calls OnStartClient() which connects the client to the server.
    4. Server calls OnServerConnect() & client calls OnClientConnect() at the same time when the client connects to the server.
    5. Client calls ClientScene.Ready() which calls...
    6. ...ClientScene.AddPlayer()...which calls...
    7. OnServerAddPlayer() on the server...which calls...
    8. NetworkServer.AddPlayerForConnection()
    9. ...
    That's as far as I've gotten. The code behind NetworkServer.AddPlayerForConnection() is pretty extensive and can (seemingly) produce multiple results. Here's a flowchart for a more visual approach to how I'm understanding things.
    Please someone from Unity get back to us on this. I'd really like to keep exploring using UNet for my project, but I'm hung up on this.
     
    Zero123 likes this.
  5. bdoom

    bdoom

    Joined:
    Apr 13, 2013
    Posts:
    12
    The unity community is dead lol.
     
  6. everystone

    everystone

    Joined:
    Jan 30, 2014
    Posts:
    7
    What about overriding OnServerAddPlayer(), and instead of directly spawning the player, spawn a temporary "loading" object. in your loading object, attach a script that calls a [Command] which passes the username string ( or whatever else data you need) from the client to the server, and the server fetches the data, instantiates the correct player object( at correct position etc from db) and invokes ReplacePlayerForConnection() ?
     
  7. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    You're somewhat correct. I handle it using Messages. I'm overriding OnServerAddPlayer and in my override when I call ClientScene.AddPlayer() I add a message to it. Once the player is finished being populated and Instantiated, I call AddPlayerForConnection() not Replace.
     
  8. Mr-Jun

    Mr-Jun

    Joined:
    Jul 1, 2015
    Posts:
    9
    Thanks for the chart you've provided.
    I'm also wondering where OnStartLocalPlayer(), and Awake() fits in all this.
     
  9. transporter_gate_studios

    transporter_gate_studios

    Joined:
    Oct 17, 2016
    Posts:
    219
    Agreed, There needs to be more detail in the documentation.

    for example:

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

    NetworkBehaviour.OnStartLocalPlayer



    public void OnStartLocalPlayer();
    Description
    Called when the local player object has been set up.

    This happens after OnStartClient(), as it is triggered by an ownership message from the server. This is an appropriate place to activate components or functionality that should only be active for the local player, such as cameras and input.

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

    OK, so

    Does the server player object call this or the client player object? or do both the server player and the client player call it?
     
  10. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    This occurs on the Local Player's machine.
     
  11. transporter_gate_studios

    transporter_gate_studios

    Joined:
    Oct 17, 2016
    Posts:
    219
    Thanks DRRosen, I've been trying to get some code to run only on the server instance of the player object, but I can't seem to get IsServer to return true. I've been using it in Start() and OnStartLocalPlayer() and neither work. OnStartLocalPlayer() obviously is not working because its only called on the client.. I figure it would work in Start() on the player script though. Hmm, im not sure where else to check if the object is the server instance of the player. any ideas? experiences with this?
     
  12. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Here's the problem with "isServer". This ONLY returns true for the GameObject that represents the host's presence in the game. Just like every player in the game is represented by ONE GameObject that returns true for isLocalPlayer, the same is said for the server. So "isServer" doesn't return true if the code is being executed on the server, it only returns true if the code is referencing the server's GameObject.

    So for example, in a test scenario I had players firing projectiles. The way I checked for "isServer" (because only the server handled dealing damage), is by having every projectile hold a reference to the player that fired it. Then when the projectile collided with something, I would check to see if the player that fired that projectile, was the server. For example...

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using System.Collections;
    4.  
    5. public class Rocket : NetworkBehaviour
    6. {
    7.    public Soldier rocketOwner;
    8.  
    9.    void OnTriggerEnter(Collider other)
    10.    {
    11.       if(!rocketOwner.isServer)
    12.          return;
    13.       else
    14.          //EXECUTE CODE HERE TO HAVE SERVER DEAL DAMAGE
    15.    }
    16. }
     
  13. tswiggs

    tswiggs

    Joined:
    Mar 13, 2014
    Posts:
    4
    Here it is a full year later and I just finished dealing with the same question. This should be page 2 of the HLAPI documentation. After about 20 hours of looking through sample projects I came up with a flow chart similar to the one you created. It's like they didn't anticipate people would need a custom network manager.
     
    wlwl2 likes this.
  14. angusmf

    angusmf

    Joined:
    Jan 19, 2015
    Posts:
    261
    This is definitely incorrect.
     
  15. angusmf

    angusmf

    Joined:
    Jan 19, 2015
    Posts:
    261
    Better late than never maybe? Try not to check isServer until after NetworkServer.Active = true. Almost all the weird init stuff with UNET is due to this problem.
     
  16. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    No...it's not incorrect...at least it wasn't at the time I made that post. I know Unity has made a lot of changes to uNet, but I don't use it anymore so I don't know if it still holds true or not.