Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Custom Networking: Server vs Client Gameobjects

Discussion in 'Multiplayer' started by MaPiDev, Apr 3, 2019.

  1. MaPiDev

    MaPiDev

    Joined:
    Aug 29, 2018
    Posts:
    21
    Hi there,

    I am currently working on the multiplayer part of my RTS game. I created my own networking solution using Enet C#. I did that because I have to handle a lot of manual packet resizing, delta compression, etc... Communication between client and server works pretty well already. However, I have problems wrapping my head around spawning networked objects. Currently, I have a "NetworkManager" where I put in prefabs so that client and server both know which prefab to spawn. Basically, it works like this:
    1. Client --> Send "Spawn Unit" command to the server
    2. Server --> Sanity checks command, spawn unit, Send "Spawn Unit" command to the client
    3. Client --> spawn unit
    This is working fine. The problem is, my units act based on a behavior tree. Now when I instantiate a unit the behaviour tree runs on both client and server. But it should only run on the server. The client receives position updates through the server. I don't exactly know what may be a good solution to this, the following is what I thought about:
    • Simply check on unit spawn if the game is a client or a server and based on that activate or deactivate the behaviour tree.
      • Con: Easy to have bugs and forget checks if the server and client code is the same codebase (probably a lot of IF conditions inside the code)
      • Pro: Only one codebase to maintain and little boilerplate code
    • Create separate client and server prefabs and spawn the corresponding prefab.
      • Con: More boilerplate code and two prefabs to maintain
      • Pro: Clear distinction between client and server, easier to maintain than a single codebase
    I would appreciate additional suggestions or any other input if you have had a similar problem.

    Thanks.
     
  2. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    403
    First off: There's probably no right or wrong way to do things.

    Other than that, I use ENet too, and have run into those same issues. Personally, I have prefabs on the client, and data about objects on the server. I have a separate builder project that builds assetbundles for the client and text files containing the data on each object or object-type for the server.

    After many reworkings, I now have a base network-object class, and an array of specific object types that inherit from the base. This has proved to be the simplest system by far.

    For traffic, the client can only ever "request" something (spawn, movement, tool-use, etc) from the server. The server does it's magic (not magic) and broadcasts results (to subsets of clients in range).

    Finally: See point one.
     
  3. MaPiDev

    MaPiDev

    Joined:
    Aug 29, 2018
    Posts:
    21
    Thanks for the answer.

    Ok, so you only have data on the server. I guess you are doing all the game simulations on the client right?
     
  4. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    403
    Well, the server controls everything. All players have a data record on the server, as do all npcs, doors, and all interactables. All game maths and mechanics are either handled or "oked" by the server. So it really is the simulation. The client is relatively dumb, it just displays the data and handles user inputs.
     
  5. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    In my custom network solution I used a concept similar to the way Unet does it, by using the same scripts client and server side and allowing in code to ask if this is a server or not. Partly because I already had over a year of work into my game using Unet when I converted my game over to my own solution.
    Code (csharp):
    1. if (JCGNetworkManager.IsServer())
    2. {
    3.     //Server side code here, client won't run this
    4. }
     
  6. MaPiDev

    MaPiDev

    Joined:
    Aug 29, 2018
    Posts:
    21
    Yep. This is currently also what I am doing now. At least for testing my networking solution it works fine.
     
    Joe-Censored likes this.