Search Unity

Converting a game to multiplayer at the end of development?

Discussion in 'Multiplayer' started by crandellbr, Dec 11, 2019.

  1. crandellbr

    crandellbr

    Joined:
    Apr 3, 2013
    Posts:
    137
    Hello. At some point in the not too distant future, I'd like to make a top-down shooter with co-op multiplayer (think Dead Ops from CoD: Black Ops). I've researched network programming many times, and the basic concepts are simple enough, but things like client-side prediction are a whole other ballpark. It's just not intuitive enough, having to manage multiple instances of a game while at the same time smoothing out varying delays between them.

    I can program the entire rest of a game stylized after Dead Ops - that's not a problem. It's just multiplayer I can't wrap my head around. I've researched it well enough to know that networking really should be built into a game from the start, but I have to ask anyway...how hard would it be for an experienced network programmer to convert an otherwise finished game? Would they generally be comfortable doing such a thing, or just be inclined to roll their eyes at the backwards approach?
     
  2. Youdaman

    Youdaman

    Joined:
    Apr 8, 2017
    Posts:
    8
    It's fine to develop the basic gameplay as single-player and then convert to multiplayer after as long as you take a modular approach and use functions for actions like shooting instead of in-lining them into your input code.

    For example:

    Code (CSharp):
    1.  
    2.     void Update() {
    3.         if (this.IsLocalPlayer) {
    4.             if (Input.GetKeyDown( KeyCode.Space ))
    5.                 InvokeServerRpc( CmdShoot );
    6.  
    and then elsewhere:

    Code (CSharp):
    1.  
    2.     [ServerRPC]
    3.     void CmdShoot() {
    4.         GameObject bullet = Instantiate( bulletPrefab, this.transform.position, Quaternion.identity );
    5.         bullet.GetComponent<Rigidbody2D>().velocity = Vector2.up * bulletSpeed;
    6.         bullet.GetComponent<NetworkedObject>().Spawn();
    7.         Destroy( bullet, 1.0f );
    8.     }
    9.  
    The above is taken directly from a code example someone created for MLAPI here: https://github.com/MidLevel/MLAPI/issues/220#issuecomment-501905747 (see my caveat comment below that one about changing the host IP if you intend to try it out).

    So when you're developing this as single-player, you would still have a CmdShoot function that gets called when the player presses the spacebar, it's just that instead of calling it directly you use MLAPI's InvokeServerRpc function and you add attributes like ServerRPC above the CmdShoot function, and then inside that there's just one extra line to what you'd have in single-layer where you Spawn the bullet. And the only other network bit is the IsLocalPlayer check before you grab user input.

    Here's the docs in relation to the above: https://mlapi.network/wiki/messaging-system/

    As for more advanced things like prediction/compensation, MLAPI also has a nice approach to this: https://mlapi.network/wiki/lag-compensation/

    As you can tell, I like using MLAPI. It's got great docs although the examples are lacking (that example linked above by a user is actually a pretty good starting point to get your head around it).

    You can code your game as a single-player experience and add multiplayer later, as long as you don't write spaghetti code and you separate gameplay actions into their own functions so that you can then add the decoration that says "only do this on the server" or "call this function on the client" etc.

    The other thing to keep in mind is disabling components or functionality you don't want other characters in the game to do. For example you want your input and controller and camera functionality to only be used on your character and not the others you see in your instance of the game world (because they need to be controlled by their respective owners). So I usually do something like this and attach it to the player prefab:


    Code (CSharp):
    1.  
    2. using MLAPI;
    3.  
    4. public class DisableNonLocal : NetworkedBehaviour
    5. {
    6.   void Start()
    7.   {
    8.     if (!IsLocalPlayer)
    9.     {
    10.       GetComponent<CameraWalkerController>().enabled = false;
    11.       GetComponent<Mover>().enabled = false;
    12.       GetComponent<AnimationControl>().enabled = false;
    13.       Destroy(transform.Find("CameraRoot").gameObject);
    14.  
    In other words, for all players that are not me, i.e. all the copies of other players that I see in my instance of this shared world we're each running separately, disable the controllers/movers and destroy their camera.

    As for how they move or animate and how that's synced, that's where assets like Simple Network Sync come into play: https://assetstore.unity.com/packages/tools/network/simple-network-sync-134256 -- you attach its components to your player and it takes care of syncing the position/rotation/animation (and any extra variables you tell it to).

    Anyway, what network library or multiplayer solution you choose is up to you. I've gone with MLAPI and SNS because they made sense to me and were well documented and supported via Discord chats with the developers.

    So yeah, in summary, make your game single-player to start, then sprinkle in the multiplayer after -- as long as you keep things modular!
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Pretty much every system in your game will have to be redesigned for a network implementation, so you're basically rewriting the bulk of the game's code. The "just multiplayer" part involves more work than the rest of the code in your game combined most likely.

    I'm sure you will find developers who want to do this for you, assuming you're understanding how much of their time you're likely to be paying for.
     
  4. crandellbr

    crandellbr

    Joined:
    Apr 3, 2013
    Posts:
    137
    Hi, thanks guys. If I had to pay for all programming, I'd want to do it the proper way and have a network programmer on board from the start. What will probably tip the balance is that I get "free" programming from myself. If I were to collaborate with a network programmer along the way, either they'd have to convert my code piecemeal, or I'd have to depend on them for tasks I would otherwise be able to do myself. Either method would be just as costly, if not more so. It might also be easier to justify it as an educational experience if I can see the clear division between my code and theirs. I'm always in the habit of writing clean and modular code, so maybe it won't be too painful.
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,770
    I would say, if you consider multiplayer later, you need design with multiplier from ground up. Even if it is just single player for now. As @Joe-Censored mentioned, it will be nightmare later, to convert, if you haven't had multiplayer in mind, while designing from the start.

    I think, if you will make in such way, that player can be played along with others as bots, it will open you doors, for multiplier implementation later.
     
    Joe-Censored likes this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Also consider you'll need to keep the network programmer on board for ongoing support. Since networking is complicated, it is prone to discovering bugs later which escape initial testing, and is affected by environment and load in ways other game systems are not. For example, a networked system can appear to work fine with 1 client connected, but fail with 4 clients connected, or work fine at a 50 ping but fail with a 200 ping.
     
  7. crandellbr

    crandellbr

    Joined:
    Apr 3, 2013
    Posts:
    137
    With co-op multiplayer I think it'll be less of an issue, as long as I'm prepared to balance for the extra player(s). I'm also interested in competitive multiplayer, though, and hopefully I'll learn a thing or two about networking from seeing it implemented with co-op. Either way, I'll make sure to keep multiplayer in mind from the start.

    And thanks again, Joe-Censored. Testing is definitely something I'm worried about. I'll have to do plenty more research just so I can be closely involved in the testing phase.
     
    Joe-Censored likes this.