Search Unity

Showcase LiteNetLib - another reliable udp library.

Discussion in 'Multiplayer' started by RevenantX, Jun 30, 2016.

  1. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    NAT punch is pretty simple thing. It used in 90% for Peer 2 Peer connections.
    LiteNetLib uses algorithm very similar to STUN (https://en.wikipedia.org/wiki/STUN) but with different protocol.
    You must have one server(master server) with "white" ip address. This server can be behind NAT but with forwared ports.
    Server example: https://github.com/RevenantX/LiteNetLib/blob/master/LibSample/HolePunchServerTest.cs
    Code (CSharp):
    1. private NetManager _puncher; - server.
    Code (CSharp):
    1. void INatPunchListener.OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token)
    NAT punch works almost in all situations but there some exceptions - when 2 clients behind symmetric NAT and in some mobile networks.
    I will create better and clear example for NAT punch.
     
    Skylander17 likes this.
  2. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    when client connects to server - you will receive NetPeer class in "OnPeerConnected" method - that will be your peer. Also you can store Server "peer" (really this is just connection betwen) by calling client.GetFirstPeer() after client.Connect(...);
    Code (CSharp):
    1. class SomeClass
    2. {
    3.     private NetPeer _serverConnection;
    4.     private NetManager _client;
    5.     public void Run()
    6.     {
    7.         _client = new NetManager(...);
    8.         _client.Connect("mysupergame.com"); //or any external ip
    9.         _serverConnection = _client.GetFirstPeer();
    10.     }
    11. }
     
  3. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    Thank you! Should the server just have a list of peer connections to keep track of them and send the messages accordingly?
     
  4. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Server(any NetManager) already have list of peers:
    Code (CSharp):
    1. public NetPeer[] GetPeers()
    2. //and faster method
    3. public void GetPeersNonAlloc(List<NetPeer> peers)
    NetManager has methods like
    Code (CSharp):
    1. public void SendToAll(NetDataWriter writer, SendOptions options)
    2. public void SendToAll(byte[] data, SendOptions options)
    3. public void SendToAll(byte[] data, int start, int length, SendOptions options)
    4. public void SendToAll(NetDataWriter writer, SendOptions options, NetPeer excludePeer)
    5. ... etc
    or you can store your NetPeers in some other place and send data directly to peers (clients)
     
  5. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    Lots of good info, the chm file wasn’t working for me when I tried it. Also, this dll doesn’t happen to work in c++ does it?
     
  6. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    No. This DLL only for C# (.net, mono, dotnetcore, xamarin)
     
  7. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    Hey, I took the script from the example that was working and the dll moved it over to my unity project but now I am getting a few errors. It recognizes the DLL is there. What did I do wrong? upload_2017-12-4_18-1-26.png
     
    Last edited: Dec 5, 2017
  8. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Show your script. And use library sources (not DLL) in unity3d (best will be with UNITY compilation symbol defined)
     
  9. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    I am sorry, what do you mean by library sources. Here is my script.

    Code (CSharp):
    1. using UnityEngine;
    2. using LiteNetLib;
    3. using LiteNetLib.Utils;
    4.  
    5. public class GameClient : MonoBehaviour, INetEventListener
    6. {
    7.     private NetManager _netClient;
    8.  
    9.     [SerializeField] private GameObject _clientBall;
    10.     [SerializeField] private GameObject _clientBallInterpolated;
    11.  
    12.     private float _newBallPosX;
    13.     private float _oldBallPosX;
    14.     private float _lerpTime;
    15.  
    16.     void Start()
    17.     {
    18.         _netClient = new NetManager(this, "sample_app");
    19.         _netClient.Start();
    20.         _netClient.UpdateTime = 15;
    21.         _netClient.Connect("127.0.0.1", 5000);
    22.     }
    23.  
    24.     void Update()
    25.     {
    26.         _netClient.PollEvents();
    27.  
    28.         var peer = _netClient.GetFirstPeer();
    29.         if (peer != null && peer.ConnectionState == ConnectionState.Connected)
    30.         {
    31.             //Fixed delta set to 0.05
    32.             var pos = _clientBallInterpolated.transform.position;
    33.             pos.x = Mathf.Lerp(_oldBallPosX, _newBallPosX, _lerpTime);
    34.             _clientBallInterpolated.transform.position = pos;
    35.  
    36.             //Basic lerp
    37.             _lerpTime += Time.deltaTime / Time.fixedDeltaTime;
    38.  
    39.         }
    40.         else
    41.         {
    42.             _netClient.SendDiscoveryRequest(new byte[] {1}, 5000);
    43.         }
    44.     }
    45.  
    46.     void OnDestroy()
    47.     {
    48.         if (_netClient != null)
    49.             _netClient.Stop();
    50.     }
    51.  
    52.     public void OnPeerConnected(NetPeer peer)
    53.     {
    54.         Debug.Log("[CLIENT] We connected to " + peer.EndPoint);
    55.  
    56.  
    57.     }
    58.  
    59.     public void OnNetworkError(NetEndPoint endPoint, int socketErrorCode)
    60.     {
    61.         Debug.Log("[CLIENT] We received error " + socketErrorCode);
    62.     }
    63.  
    64.     public void OnNetworkReceive(NetPeer peer, NetDataReader reader)
    65.     {
    66.         _newBallPosX = reader.GetFloat();
    67.  
    68.         var pos = _clientBall.transform.position;
    69.  
    70.         _oldBallPosX = pos.x;
    71.         pos.x = _newBallPosX;
    72.  
    73.         _clientBall.transform.position = pos;
    74.  
    75.         _lerpTime = 0f;
    76.     }
    77.  
    78.     public void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader,
    79.         UnconnectedMessageType messageType)
    80.     {
    81.         if (messageType == UnconnectedMessageType.DiscoveryResponse && _netClient.PeersCount == 0)
    82.         {
    83.             Debug.Log("[CLIENT] Received discovery response. Connecting to: " + remoteEndPoint);
    84.             _netClient.Connect(remoteEndPoint);
    85.         }
    86.     }
    87.  
    88.     public void OnNetworkLatencyUpdate(NetPeer peer, int latency)
    89.     {
    90.     }
    91.  
    92.     public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
    93.     {
    94.         Debug.Log("[CLIENT] We disconnected because " + disconnectInfo.Reason);
    95.     }
    96. }
     
    Last edited: Dec 5, 2017
  10. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    So I did what I think you said and I just added the scripts instead of the dll and still had the same problem with the same errors.

    upload_2017-12-4_21-45-10.png
     
  11. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Hmm. This is very strange. What version of Unity3d are you using? Can you send to me archived project?
    Maybe you already have NetManager class and you get conflicts?
     
  12. Reddoge

    Reddoge

    Joined:
    Feb 19, 2016
    Posts:
    10
    I totally forgot that I had another NetManager class in another folder..... So that fixes that rookie mistake. Do you still think I should use the source files more than the DLL, or should the DLL be fine?
     
  13. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Better will be source. (especially if you target mobiles) because of some epic unity3d network bugs.
     
  14. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    New update! LiteNetLib 0.7.7
    • Removed unnecessary flow nodes
    • Improved sending speed
    • Thread safe NetPeer.Send and NetManager.PollEvents
    • Packet loss statistics
    • Added NetDataReader clone method.
    • Optimizations
    https://github.com/RevenantX/LiteNetLib/releases/tag/0.7.7

    And now in master branch next LiteNetLib version that has neat new features, fixes (and new bugs :) )
    • Reliable disconnect
    • Connect with user data and connection approval system
    • Refactored NetSerializer (documenation isn't updated at this time)
    • Connection logic stability
    • Unity improved defines (for source version)
    • Support to bind socket to specific IPAddress
    Some of this features can be unstable. So i will be very grateful if you help)
     
    nxrighthere likes this.
  15. BlankMauser

    BlankMauser

    Joined:
    Dec 10, 2013
    Posts:
    138
    I am trying to mess with the Unity3D Sample and im getting some compiler errors:


    Do I need to update to a specific version of Unity3D even though these don't seem Unity API related?
     
  16. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    i forgot to update library in UnitySample. This was fixed.
     
    BlankMauser likes this.
  17. alexr1221

    alexr1221

    Joined:
    Mar 5, 2016
    Posts:
    70
    Thank you for this amazing project! I'll try to add features and optimizations whenever I can. Maybe I'll try to add a data compressor (huffman)
     
  18. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @alexr1221 thanks!

    > data compressor (huffman)

    Thanks but i don't need compressor) I leave compressor selection to users (and if they need this)
     
    Last edited: Jan 18, 2018
  19. alexr1221

    alexr1221

    Joined:
    Mar 5, 2016
    Posts:
    70
    Ok no problems!
     
  20. grimunk

    grimunk

    Joined:
    Oct 3, 2014
    Posts:
    278
    I would imagine that any limit would be due to hardware, not software.
     
  21. Deleted User

    Deleted User

    Guest

    Hello, thank you for the great work!

    By saying "Always use library sources instead of precompiled DLL files." do you mean that in unity I should use the actual source code instead of LiteNetLib.dll? If yes, why?
     
  22. grimunk

    grimunk

    Joined:
    Oct 3, 2014
    Posts:
    278
    It could mean a couple of things: Don't use DLL assemblies or don't use DLL executable code - they are two different things but have the same file extension.
     
  23. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Yes. Because there some platform specific bugs in Unity3d that fixed under defines.
     
    Deleted User likes this.
  24. grimunk

    grimunk

    Joined:
    Oct 3, 2014
    Posts:
    278
    However, in the case of non-assembly .DLLs, compiled from C/C++ code and used via p/invoke, such bugs aren't meaningful. I imagine that same would be true for LLVM bitcode libraries that originate from a different language. ENet is an example that comes to mind.
     
  25. destructor465

    destructor465

    Joined:
    Jan 30, 2016
    Posts:
    18
    Hi, in LiteNetLib 0.7.7.1 im missing OnConnectionRequest and ConnectionRequest, why they been removed?
     
  26. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @destructor465 they not removed. They didn't added in that version. In master branch (possibly unstable) 0.8.x
    Latest stable 0.7.7.1 without that features.
     
  27. destructor465

    destructor465

    Joined:
    Jan 30, 2016
    Posts:
    18
    So I need to use master branch which might be unstable to use this feature, why stable release doesn't have it? Is it new 0.8.x feature?
     
  28. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    Yes.
    Yes.
     
  29. DoubleZeroCool

    DoubleZeroCool

    Joined:
    Feb 19, 2018
    Posts:
    4
    Hey Revenant, I am trying to use your library for my game. Everything seems to be simple enough, except that I have no idea how I can plan the architecture for my project. I am using Unity, and got the basic communication done for one screen (login, register). Now I am trying to move to my game screen, and I am not sure how to use the library to separate my logic. For example, how can I have multiple listeners? I have one of my controller classes implement INetEventListener, but that would mean that all of the networking logic should be in there? I need some tips if somebody knows
     
  30. DoubleZeroCool

    DoubleZeroCool

    Joined:
    Feb 19, 2018
    Posts:
    4
    I took a closer look at how I can set it all up today. I ended up completely refactoring the entire prototype. Instead of implementing INetEventListener I now used the already existing EventBasedNetListener class, and I subscribed in my Start functions and unsubscribe in OnDestroy, now I have a UI layer, a controller layer for actions. I simply access my Manager class to give me an instance of server connection and I pass it to all the controller methods. A controller class for each UI screen, seems good enough for me, except for many static keywords I had to use. Until next time :)
     
  31. destructor465

    destructor465

    Joined:
    Jan 30, 2016
    Posts:
    18
    @DoubleZeroCool I think, it better to use one controller and just don't destroy it on load, so you can move across scenes without losing it. You are free to split server and client if you don't want to keep everything in one controller but still don't destroy them on load, this way you will be able to avoid static keywords. And then start client or server according user input, I would recommend singleton pattern for this one. Also you could use SceneManager events to know when scene is changed.
     
    Last edited: Feb 22, 2018
    Deleted User likes this.
  32. DoubleZeroCool

    DoubleZeroCool

    Joined:
    Feb 19, 2018
    Posts:
    4
    Thank for info. I have a dedicated server running and my client and server are really two separate projects. I have a question, do people use containers and dependency injection for this type of software? I dont see a problem setting up autofact for both the server and the client, any downsides to it?
     
  33. Homicide

    Homicide

    Joined:
    Oct 11, 2012
    Posts:
    657
    Hi. Im new to the unity networking, and so far ive had no luck establishing a connection beyond my router.

    I can connect internally, or across hamachi vpn with ease, but public ip peer to peer has been ugly with UNet

    This caught my eye, so i browsed over the web site and read me, but i got lost when it came time to use, install, reference ... this.

    Is there any setup for unity useage instructions? Or is it best for a newcomer to not use this?
     
  34. Azmodan76

    Azmodan76

    Joined:
    May 16, 2016
    Posts:
    4
    These are few easy steps you can follow in order to start using it:
    1. git clone or download the last stable source code
    2. From the solution copy the sources of project 'LiteNetLib' into your assets folder - preferably create a sub-folder named appropriately and put it there so it is well organized. (Note copy the 'LiteNetLib\*.cs' files including the sub-folder 'LiteNetLib\Utils\*.cs')
    3. In unity make sure you add the 'UNITY' (without quotes) define
    4. That's it. Start using it and never be afraid of using something new even if you are beginner!

    That is so far how I am playing with it and have no problem. The sub project 'LibSample' gives good usage examples.


    If I am missing something or am giving bad advice - please correct me!
     
    Last edited: Feb 26, 2018
  35. Deleted User

    Deleted User

    Guest

    Hi there. Why would you need "UNITY" define? Thanks.
     
  36. Azmodan76

    Azmodan76

    Joined:
    May 16, 2016
    Posts:
    4
    Because I am using the stable version 0.7.7.1 and in the README of that version it states:
    That is why ;-)
    And it simply do not compiles without it ;-)
    This may be changed in the latest UNstable master branch. So please every time consult with the README of the version you are using!
     
  37. Deleted User

    Deleted User

    Guest

    Hm, I am using the same stable branch without this define and it works perfectly. Futhermore, there is no any part of code that starts with "#if UNITY"
     
  38. Azmodan76

    Azmodan76

    Joined:
    May 16, 2016
    Posts:
    4
    Take a look at NetUtils.cs line: 238
    But then again as I said: "If I am missing something or am giving bad advice - please correct me!" so you did corrected me. What I am relaying as information is just my experience. I do not pretend that I am an expert in this lib.
     
  39. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    In master branch there is no need to use UNITY define. Only in stable for logging and fixes for some mobile platforms in NetSocket.cs code.
     
  40. arcturgray

    arcturgray

    Joined:
    Nov 20, 2016
    Posts:
    12
    Hello there!
    First of all, thanks for your great library, it works well.

    I have one small issue though. Maybe I just do not understand something.

    For example, I create a server manager with maxConnections == 3, connect 3 clients to it and then disconnect one of them by calling serverPeer.Disconnect() on the client. After that I can't connect to the server anymore, despite the fact that there are only 2 connections left. It seems like peer that on the server represents disconnected client is not really disconnected (peer that is passed to the PeerDisconnectedEvent callback has status Connected). After that I see that server keeps rejecting all further connection requests.

    I've managed to solve it by calling serverManager.DisconnectPeerForce(peer) in PeerDisconnectedEvent callback on the server. As I see in the source code, this method call sets peer's state to Disconnected and enqueues disconnected event, so to avoid looping I have to check peer's status and if it is already set to disconnected, do not call force disconnect.

    It works, but I am pretty sure that I do something wrong. What's the intended workflow?

    PeerDisconnectedEvent is called:
    1) When we on our side disconnect some peer, in which case peer passed to this callback will have Disconnected or ShutdownRequested state.
    2) When remote end disconnects from us, in which case peer passed to this callback will have Connected state. So here it is more like "OnDisconnectionRequest".

    Is that correct?
     
    Last edited: Mar 8, 2018
  41. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @arcturgray there is some bugs with disconnect in master branch. I will fix them soon.
     
  42. QuadrantGames

    QuadrantGames

    Joined:
    Jan 10, 2016
    Posts:
    20
    Hey I really like the simplicity and pluggability of this library into unity, but I recently discovered the server stack I want to use doesn't support UDP, and the type of messaging my game uses technically doesn't need UDP. Are there ever plans to include TCP support? I've looked around for a similarly supported/developed tcp library that plugs nicely into unity monobehaviours and I can't seem to find anything I like.
     
  43. Deleted User

    Deleted User

    Guest

    You can use RUDP, it's basically the same as TCP. Just use ReliableOrdered message type as your primary delivery method.
     
  44. QuadrantGames

    QuadrantGames

    Joined:
    Jan 10, 2016
    Posts:
    20
    I want to use https://aws.amazon.com/elasticloadbalancing/details/#details Network Load Balancing to route connections to different servers, I don't believe RUDP is supported.
     
  45. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    No, there is no plans to support TCP. Because this library created only for one purpose, reliable UDP.
    There is no specific integration to unity3d. LiteNetLib doen't depend on Unity3d. You can use plain TCP sockets (or simplified classes like TCPClient) almost like LiteNetLib.
     
  46. auroxi

    auroxi

    Joined:
    Dec 31, 2012
    Posts:
    85
    Ok so this looks promising for real time communication however I am trying to send a class through LiteNet and it's not happening at all. Some of the commands in the documentation are missing.

    SubscribeReusable is no longer part of NetSerializer
    RegisterCustomType is also no longer part of NetSerializer

    Sometimes I am wanting to send a simple string to the client, and sometimes I want to send a class which is currently:

    Code (CSharp):
    1. public class TestClass {
    2.     public bool testBool1;
    3.     public bool testBool2;
    4.     public string stringProperty;
    5. }
    How can I do this? I have built from the latest source.

    Thanks in advance..I got Unity connecting to a c# console server instantly and would be fine if I only had to send strings :)
     
  47. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @auroxi if you use version from master branch - use NetPacketProcessor.
     
  48. RevenantX

    RevenantX

    Joined:
    Jul 17, 2012
    Posts:
    148
    @auroxi use NetPacketProcessor on server too. And don't create it every time on receive - because method "SubscribeReusable" very slow. It caches some things and use a lot of refelction.
     
  49. auroxi

    auroxi

    Joined:
    Dec 31, 2012
    Posts:
    85
    @RevenantX Sorry I eventually realised I should be doing that also. I've just got it working, it's because of the namespace in the server class, me being stupid! :)
     
    Last edited: Apr 10, 2018
  50. TriangularCube

    TriangularCube

    Joined:
    Apr 6, 2016
    Posts:
    16
    Hi there!

    First off, this library is fantastic, and I want to thank you for keeping it up!

    Here's a question though, there's currently no way to unsubscribe from NetPacketProcessor? Or is there something I'm completely missing?
     
    Deleted User likes this.