Search Unity

Unity Multiplayer UNET Unofficial Documentation (Errors, Workarounds, Best Practices)

Discussion in 'Connected Games' started by vis2k, Apr 5, 2016.

  1. vis2k

    vis2k

    Joined:
    Sep 4, 2015
    Posts:
    3,242
    After spending another day with random UNET errors, I decided to share my list of UNET errors and workarounds, as well as some best practices and explanations.

    My hope is that others share their knowledge as well in order to decrease general frustration.
    Perhaps a moderator can even make this a sticky post if it becomes bigger. Perhaps a UNET developer can even clear things up more.

    Errors & Workarounds
    • Did not find target for sync message: ...
      • Explanation: Happens when Unity sends a SyncVar (etc.) update to a client's GameObject that doesn't exist anymore. This commonly happens for Bullets, Arrows etc. which may receive one or two sync messages still after being destroyed.
      • Workaround: using Reliable Sequenced channel works sometimes, except when it doesn't. The best thing to do is to ignore it.
    • Failed to spawn server object: ...
      • Explanation: Happens when you use NetworkServer.Spawn on a object that isn't known as a spawnable object on the client.
      • Workaround: add that object to the NetworkManager's spawnable object list.
    • SyncLists aren't properly synced to the Client (the list is empty without any errors being shown)
    • ReadString out of Range / ReadBytes out of Range
      • Explanation: Happens after errors in OnSerialize/OnDeserialize. You don't see those errors directly, only UNET sees them. The result is a messed up packet. I reported it as #786248 and it was confirmed already.

    Best Practices & ELI5

    Attributes:
    • [Server] means don't allow a client to call that method (throws a warning or an error then)
    • [ServerCallback] means don't allow a client to call that method (throws no warning). Can be used if something like Start or Update should only be called on the server
    • [Client] means don't allow a server to call that method (throws a warning or an error then)
    • [ClientCallback] means don't allow a server to call that method (throws no warning). Can be used if something like Start or Update should only be called on the client
    Commands:
    • Use [Command] tag and 'Cmd' prefix for the function name like 'void CmdTest()'
    • Call this from a client to run this function on the server. Make sure to validate input etc.
    • Can't call this from a server. Use this as a wrapper around another function if you want to call it from the server too.

    Creating and Destroying GameObjects:
    • Create by using Instantiate as usual, then use NetworkServer.Spawn(go).
    • Destroy by just using NetworkServer.Destroy.
    Headless Mode:
    • Linux executables can run in headless mode
    • Make sure to do something like 'if isHeadless then StartServer()' too, otherwise nothing will happen. Read here to learn how to detect headless mode.

    NetworkProximityChecker:
    • Make sure that you also have a Collider on the same GameObject, otherwise Physics won't detect it, hence the checker thinks it's not around, hence UNET makes it invisible.
    Network Send Interval:
    • You can try to set it, but UNET will still send in a different interval, at least for a while after the game started.
    NetworkAnimator:
    • Triggers have to be called seperately and aren't synchronized automatically. The rest kinda works, except when it doesn't. I usually synchronize important parameters like health, speed etc. to the client and then let the client set the Animator paraemters, without using a NetworkAnimator at all.
    NetworkBehaviour:
    • Use this instead of MonoBehaviour if this object should be synchronized.
    • You can use isServer, isClient, isLocalPlayer for control flow. Note that sometimes more than one of them are true at the same time (e.g. when running as host).

    NetworkIdentity:
    • Server Only means the client won't see it, it only exists on the server.
    • Local Player Authority means that the client can cheat.
    NetworkManager:
    • Channels: Reliable Fragmented is the only channel that I use. Everything else randomly fails at some point when your SyncVars/SyncLists get more and bigger. I also use two of those channels, because I read somewhere that UNET uses the second channel when the first one is too full.
    • NetworkSimulation isn't expected to work (someone said that on the forum).
    • The 'Round Robin' spawn method spawns entities at one spawn point after another, starting again at the first one after the last one.
    • Don't forget to set the Timeouts to something big enough, so that people don't immediately disconnect if they lag for 1 or 2 seconds.
    NetworkLobbyManager:
    • Use their example from the Asset Store and then setup your own play scene.
    • It has a playerPrefab (inherited from the NetworkManager) and a gamePlayerPrefab property. Use the latter one.

    NetworkTransform:
    • It's laggy for everyone because the Interpolation doesn't work right. Someone posted a better version somewhere on the forum, I'll link it here if I find it again.
    RPCs:
    • Use [ClientRpc] tag and 'Rpc' prefix for functions like 'void RpcTest()'. The server uses an Rpc to run that function on clients.
    • They are sent to all observers, not just to one client (http://forum.unity3d.com/threads/suggestion-globalrpc-observerrpc-targetrpc.382486/). Use a custom message if you want to send something to all players or just one player. Note that 'TargetRpc' was planned forever and seems to be in Unity 5.4.
    SyncVars:
    • Are used to synchronize a variable from the server to all clients automatically. Don't assign to them from a client, it's pointless.
    • Don't let them be null, you will get errors.
    • You can use int, long, float, string, Vector3 etc. (all simple types) and NetworkIdentity and GameObject if the GameObject has a NetworkIdentity attached to it.
    • You can use hooks

    SyncLists:
    • Don't modify them in Awake, use OnStartServer or Start.
    • SyncListStructs use Structs. C# structs are value types, just like int, float, Vector3 etc. You can't do synclist.value = newvalue; You have to copy the element, assign the new value, assign the new element to the synclist.
    • You can use hooks like so:
      • Code (CSharp):
        1. // for the official things
        2. [SyncListString(hook="MyHook")] SyncListString mylist;
        3. void MyHook(SyncListString.Operation op, int index) {
        4.     // do things
        5. }
        6.  
        7. // for custom structs
        8. [SyncListString(hook="MyHook")] SyncListStructCustom mylist;
        9. void MyHook(SyncListStructCustom.Operation op, int index) {
        10.     // do things
        11. }

    Time Synchronization:
    • Network.Time is from the old networking system. I developed my own Time synchronization because we sometimes need to know the server time. I added one NetworkTime GameObject to the Hierarchy and then added a NetworkTime Script to it, that simply sends the server time to the client every now and then. The client then calculates the time difference between client and server and saves it as 'offset'. You can then easily calculate the server time by using the client's Time.time + offset.

    WebGL:
    • If a WebGL client should be able to connect to a server, then the server's NetworkManager has to have WebSockets enabled.
    • You can't use a server in WebGL because nothing can connect to it. You can only use WebGL for clients.
    • If WebGL just crashes without any notice, then it's most likely because of a UNET error. Try to do the same again in the Editor on in a Build, see the error, fix the error, try again in WebGL.

    UNET META
    Bug Reporting:
    • Posting bugs on the forum doesn't seem to help much. Always use the Bug Reporter (in the Unity Help menu). You will get a case number and Unity's Q&A team will look at it! This actually does work, unlike bug reporters in Microsoft, Steam etc. (Note: use the latest Unity version, add a good description, attach a project and maybe a screenshot)
    • Unity Networking on the Issue Tracker
    Source Code:
    Phase 2 and 3:
    • They talked about a Simulation Server. Aparrently we can use that as an API to communicate with UNET clients from our custom servers. My guess is that it will be a C# or C++ library.
    Relaying:
    • You need Relaying when two clients want to play with each other. Usually you can't just host a server on your own computer, it requires port forwarding. Relaying is like a proxy on the internet that simply acts as a server, so that two clients can talk to each other without port forwarding. You don't need that in most cases, for example a MMO will always have a server running on the internet, clients aren't even supposed to host their own.
    Server Hosting:

    Protecting your server source code:
    • Your Scripts can be seen easily via ILSpy etc. in the Assembly-CSharp.dll file that ships with Windows, Mac, Linux builds
    • IL2CPP is the solution, but that only works for WebGL (and some others?) so far. No one knows if/when they will add that for Linux/Windows/Mac too. IL2CPP hides your code because it converts it to C++ and then to Assembly. There is no way back to your C# code then.
    • Code Obfuscation is another option, but there seems to be no good solution for Unity+UNET yet (especially since SyncVars/SyncLists/SyncListStructs are often name dependend and cause errors if renamed etc.
    • Packing Windows executables with Themida etc. works, but will only alert virus scanners and is revertable anyway.
    • Virtualization would work and make unpacking far too hard to be worth it. Not sure if this works well with Unity though.
    • Only release WebGL builds if you really want to protect your server code.
    UNET IRC (thanks to @softrare):
    • If you want to contact the Unity UNET guys there is also an IRC channel: "We have an IRC channel dedicated to UNET! Join us on Freenode in the #unity3d-unet channel." source: http://wiki.unity3d.com/index.php/UNET
    UNET Developers:
     
    Last edited: Apr 12, 2016
    akuno, tobetobe, shamsfk and 10 others like this.
  2. softrare

    softrare

    Joined:
    Jun 12, 2011
    Posts:
    429
    I would agree to sticky your post ;)

    If you want to contact the Unity UNET guys there is also an IRC channel: "We have an IRC channel dedicated to UNET! Join us on Freenode in the #unity3d-unet channel." source: http://wiki.unity3d.com/index.php/UNET
     
    Last edited: Apr 5, 2016
  3. vis2k

    vis2k

    Joined:
    Sep 4, 2015
    Posts:
    3,242
    Thanks, added it to the post.
     
  4. or113

    or113

    Joined:
    Nov 5, 2016
    Posts:
    41
    Thanks for this awesome post, already favorited it.
     
    vis2k likes this.
  5. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    632
    Look how amazing this step-by-step doc is with pictures, completely up-to-date:
    https://unity3d.com/learn/tutorials/topics/multiplayer-networking/network-manager?playlist=29690

    But what about the lobby? Staging? Anything BEFORE the game starts? What about matchmaking?

    The docs are sparse regarding lobby, matchmaking, and the general flow of a lobby (with the new stuff -- the asset store demo uses ancient techniques and is quite bloated compared to other wonderful examples and doesn't focus on matchmaking). What started as a Unity Answers post ended up being a mass research project <QQ>as it was never answered - not even after submitting a ticket 1 month+ ago *tears*</QQ> and updated every time I reached a new milestone. Still WIP, still incomplete. Feel free to ping in the general flow of a lobby with matchmaking:

    http://answers.unity3d.com/questions/1271635/multiplayer-lobbystagingmatchmaking-flow-quickstar.html

    ^ This utilizes the NetworkLobbyManager COMPONENT with a very basic matchmaking flow (1 button matchmaking) and the latest techniques that is, so far, an incomplete thought. Hopefully a dev will chime in one day.
     
  6. VictorElselam

    VictorElselam

    Joined:
    Feb 9, 2017
    Posts:
    2
    @vis2k thank you so much for this, specially this part:
    ReadString out of Range / ReadBytes out of Range
    • Explanation: Happens after errors in OnSerialize/OnDeserialize. You don't see those errors directly, only UNET sees them. The result is a messed up packet. I reported it as #786248 and it was confirmed already.
    I was like 12 hours + trying to debug the messed up packages and it didn't make any sense.
     
    vis2k likes this.
  7. vis2k

    vis2k

    Joined:
    Sep 4, 2015
    Posts:
    3,242
    Check out HLAPI CE (see my signature). I used some safety mechanisms there so that those errors are detected clearly and in place, instead of randomly 5 minutes later.