Search Unity

Think twice before adding Multiplayer to your game.

Discussion in 'General Discussion' started by CarterG81, Mar 21, 2016.

Thread Status:
Not open for further replies.
  1. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    EDIT2: As of 4/29/2016, I can confirm that the majority of my frustration was due to an enormous bug in the asset I was using (unable to send large packets) as well as a lack of documentation. Both of which have been resolved by the developer. The documentation of Forge received a major update, and the bug has been fixed. I will hopefully find the time to work on writing up a tutorial for others to be able to stream huge worlds / thousands of gobs across the network using Forge. I am still fleshing things out to sync all current features across the network now that multiplayer networking actually works! If all goes well, I can restore my reference to Forge Networking as the best solution.

    EDIT: I should have noted I am not actually doing any network programming. I'm just using networking tools. (UNET, Forge, etc.)

    It is incredibly time consuming if you do not have any network programming experience. Even with powerful networking packages like UNET, Forge, or Photon, it is a PITA.

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

    Even with Forge networking, this is getting to the point of endless frustration, where I am just about to abandon what feels like hundreds of hours of work (but is really probably just around 100) & just make the my damn game singleplayer. I'm not going to, being so freakin' close to completing multiplayer, but

    "Got dangit Bobby!"

    People with experience can do in a few minutes what is taking me endless hours to figure out. Doesn't help that the Forge developers are so backlogged & still trying to catch up that they barely respond. They're in the process of updating the documentation & catching up on support, but those are the two things I need to progress. When I do catch them or get a response, all is well in a few minutes.

    "If only I had that experience too!"



    I think I've spent longer trying to figure out a handful of things required of networking than any other feature I have ever done. After today, I have officially spent 25 hours, 41 minutes, & 59 seconds on trying to stream a large open world from the Server, to a Client, via Forge Networking. It sounds more complex than it actually is. If I knew what I knew now & had even a tiny bit of networking experience to boot? Would have taken about an hour.

    The vast majority of that time was spent trying to figure out a way to do it. Not doing anything, but scratching my head & adjusting code line by line, poking at it until it starts to work (only to fail later if it does). Not programming, not actual work, just sitting there banging my head in frustration

    "HOW THE HELL DO I DO THIS?!?!?"


    I'm really, really close now, but yet again I'm stumped & after a few hours can't figure out how to send a freaking BYTE ARRAY across the network from Server to Client. That super simple thing is apparently mind-boggling to figure out. All the rest of the time was setting up multiplayer the wrong way, and dealing with an incredibly inefficient method that constantly locked up the Unity Editor. Now that I figured out a super efficient method, all is well, except that I can't do a got-dang simple thing like send a single byte array. The work never ceases to end!

    For Context
    Here are the most time-consuming single-tasks of developing my game.
    There is plenty more to this, but I try to keep track of a single task as best as I can. Sometimes I bag a bunch of tiny tasks into "One thing" or "One feature".

    Take note where Multiplayer is in BOLD.

    This list is from most time-consuming tasks to least.
    • [Forge Multiplayer] Proximity Load / Stream World from Server to Client (25h 41m 59s)
    • [UNET Multiplayer] Learn how to Add Player & Customize Player based on character choice. (15h 5m 52s)
    • [UNET Multiplayer] Read Documentation & Implement Basics (14h 10m 12s)
    • [Prototype New Feature: NPC's] (10h 34m 5s)
    • [Team Management] Add new employee to project, catch up to date, setup artist tools, consultation & decision making, etc. (9h 21m 22s)
    • [Revisit Project after Long Hiatus] (9h 21m 22s)
    • [Forge Multiplayer] UNET to Forge Conversion (8h 47m 39s)
    • [GUI] Create player's entire GUI & GUI system, code, etc. (8h 34m 46s)
    As you can see, the Multiplayer component of my project is incredibly time consuming for "a single task", only matched by the GUI...which was the hardest thing I've ever done before multiplayer.

    NPC's weren't difficult, but were time consuming & complicated, plus it was one of the first prototypes I did so I setup more than just some prototype AI. It's basically creating a whole scene. In another game my most time-consuming feature was procedurally generating an entire universe, which took 9-12 hours. Was pretty easy, but time consuming. GUI & Networking were incredibly difficult or endlessly frustrating. Working with anything "Unity" is usually endlessly frustrating too, but always under 5-8 hours to "learn one thing".

    So multiplayer? What do I think of that?



    Thanks for letting me

     
    Last edited: Apr 29, 2016
    GibTreaty, MD_Reptile, Tomnnn and 5 others like this.
  2. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Just to note, adding multiplayer is frustrating because I lack the experience. Although it doesn't help the documentation of almost everything networking related is difficult / sparse, it's mainly just that lack of network programming experience.

    And no, adding multiplayer to a game is NOT, but does feel:

    UNACCEPTABLE!!!!!!!!!!!!

     
    Tomnnn, Acissathar and tatoforever like this.
  3. Wrymnn

    Wrymnn

    Joined:
    Sep 24, 2014
    Posts:
    382
    :D

    Well, think kinda put me off from implementing multiplayer into game after its in playable state :D

    But thanks for the info!
     
    CarterG81 likes this.
  4. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    I am mostly frustrated because I am so desperate to start seeing a real game from my project. I've been working on the core systems for soooooooooooooooooooo long. I just want to start testing the game design, gameplay systems, etc. But the idea of adding in multiplayer AFTER the project is completed? That sounds like so much extra work, I want to make sure multiplayer is put in from the start.

    A lot of it I just whiz by coding like a pro, but just like with anything you lack experience with, there is that huge delay when you just STOP, hit a brick wall, and realize "I have absolutely no idea how to do that..." The hours pile up after that point, often with nothing to show for it.

    And with other features I've never done before, they were nowhere near as difficult to learn. Although implementing LUA to my custom engine was pretty damn frustrating, having to deal with horrible C++ bindings & a complete lack of experience with C. (Not sure if I ever succeeded with that, I don't remember, but it was difficult because of the lack of documentation/resources. The only thing that helped was the Game Coding Complete book, and only in part.)

    Procedurally Generating Worlds was by far the best thing to ever learn, mostly because I just made it all up in my head with no help or resources. It was a freaking blast to do. Most fun thing I've ever programmed by a large amount, and although time consuming...it was just awesome & sooo much easier than I thought it would be. Loved that so much. Also enjoyed working on my own engine, but those Unity Assets save a lot of time & like I said...I just want to finish my first game already.
     
    theANMATOR2b likes this.
  5. Wrymnn

    Wrymnn

    Joined:
    Sep 24, 2014
    Posts:
    382
    Doing some infinite procedural stuff of my own as well :D We`ll see how it goes, if I decide to put there some networking.

    I did not go for multiplayer from start, because from my experience, you have to set the Goal of project state (prototype, alpha, beta) the smallest.

    And its better to lack multiplayer, and have good SP game, than have no game at all, because you either burn out (which is the most dangerous thing in private indie development), or you give it up completely.
     
    CarterG81 likes this.
  6. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Great point. Fighting burnout is truly the most difficult single task of all, by an enormous margin.
     
  7. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,368
    I've spend a large amount of time working with network systems and I still believe I have a long way to do in order to be pro-efficient. As you said, Network programming is time consuming, not only that, it's actually quite broad and large.
    You ever heard the saying "If you think game programming is hard, then try network programming". Network programming is difficult period. :D
     
    CarterG81 likes this.
  8. willemsenzo

    willemsenzo

    Joined:
    Nov 15, 2012
    Posts:
    585
    So what do you expect? You're basically trying to drive a bike without sidewheels, while you never even been on a bike before. Maybe you should take that into account.
     
  9. Farelle

    Farelle

    Joined:
    Feb 20, 2015
    Posts:
    504
    hehe, i have not tried networking yet, but I was trying to figure out for a while how to do procedural generated caves with a node based system, NOT using voxels and make them natural looking...bah! XD i still feel like sitting infront of that rubix cube :p
     
    CarterG81 likes this.
  10. darkhog

    darkhog

    Joined:
    Dec 4, 2012
    Posts:
    2,218
    Don't try to send a byte array. Send single bytes, in sequence, perhaps with some header information before hand such as how big that array has to be and what kind of data is beforehand..
     
  11. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    What? This makes no sense and is horribly inefficient
     
  12. AwesomeX

    AwesomeX

    Joined:
    Sep 10, 2013
    Posts:
    116
    For me, when it comes to networking, if I get hung up on something, it's probably something that has very little to no documentation on, and I have to spend hours/days trying to get it to work. But once I know how to do a certain thing, I just keep using that implementation.

    So yeah, I agree to some amount, multiplayer definitely makes the work 100x as much.
    But really, the only thing that makes it difficult, is if you don't know HOW to do something, not actually doing that thing.

    So if you have lots of documentation and script snippets, along with experience with that solution, or networking in general, then it can be EZ.
     
    CarterG81 likes this.
  13. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Networking isn't something you want to guess at. Ever. It's got a few narrow right ways and lots of wrong ways. The wrong way in every case is lots of small packets, these will come with a huge packet overhead. You send 1 byte? that's actually roughly 30 bytes by the time its sent due to packet and transport overhead, you can't avoid it.

    This topic is basically what I warned Unity would happen with UNet. Democratizing multiplayer networking is *not* giving us a million flexible ways to do something. It's instead being very clear, very authoritative and LEADING people. It's telling us directly the RIGHT way to do it.

    You really want to dictate this. People are best off being told directly right from wrong when it's shark infested waters*



    *sharks are actually nice, just an old saying! Don't hit me, @holliebuckets
     
    moco2k, larku, Fera_KM and 7 others like this.
  14. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,023
    If you want to get serious about networked multiplayer, you need to build a bunch of simple multiplayer games as practice before trying to convert a large project to multiplayer. For example, before trying to add multiplayer to a large open world game, try implementing networked pong and networked checkers. You have to get practice on the basics of network gaming before trying to add networking to a larger game.
     
    aer0ace likes this.
  15. Acissathar

    Acissathar

    Joined:
    Jun 24, 2011
    Posts:
    677
    After seeing your avatar and reading through the first post, I was going to be very disappointed if I didn't see this. :)
     
    CarterG81 likes this.
  16. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    Glad you're getting it sorted.

    No idea how to use things like UNET, Forge, etc but in my day job the apps need to work over a network (usually but not always a LAN). In C# you just do something like this:

    byte [] message = Encoding.GetEncoding (...ANSICodePage).GetBytes(data) where data is simply a string containing the data to be sent.

    Then just do a socket.BeginSend and reference your corresponding EndSend callback function.

    Of course there are different ways depending on how you want to do it. But that is the gist of it and how I generally do it. Just set up event/callback functions and be notified of incoming data, sending process finished and so forth.

    It's pretty simple normally but maybe for some reason with Unity you cannot do it this way. No idea. Haven't messed with multiplayer game stuff since the Blitz UDP and C++ DirectPlay days.
     
    Last edited: Mar 21, 2016
    CarterG81 likes this.
  17. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363
    I think it depends if your game really needs it. For example if you were making a game like Fez, you wouldn't really need multiplayer and it probably wouldn't add much. And if you implemented it and did it badly it would even detract from the game and give you lots of negative reviews.

    As a compromise, you could add a two-player mode for two game-pads. Or game pad and keyboard. Then it is technically multiplayer but without all the heartache.
     
    CarterG81 and dogzerx2 like this.
  18. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,822
    What your title should say rather is...

    Think twice before making a game, if it is going to be multiplayer or not...

    BTW : uLink IMO is still the best, most efficient solution for doing multiplayer with Unity. Unfortunately it is no longer supported/maintained :(
     
  19. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Well to be completely honest, I expect these networking solutions (UNET, Forge, etc.) to have much better documentation, and to all around just work "better".

    It's not like I am doing any actual network programming. I'm just using the tools I'm provided, which although seem great & save me all that time/effort, still are far from perfect.

    Once I finish my networking in my project, all I have to do is setup a tutorial for others and they will be able to add networking easily. That documentation will suddenly take it from "OMG WTF THIS IS SO HARD" to "Wow, that was incredibly easy. And now it works!" (If they're trying to do something similar to me, of course.)
     
    Last edited: Mar 21, 2016
    tatoforever and Ryiah like this.
  20. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    This is 100% spot on.

    It's actually not the network programming that's hard. I'm not doing any of that, since I'm just using tools. Instead I'm just suffering from a lack of documentation (as are so many who use UNET.)

    Every single word here is so spot on, I wish I could give a Mega-Like or 5x Likes, instead of just the one.
     
    tatoforever likes this.
  21. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    I'm actually going to have to disagree, even though this sounds like the normal 'good advice'.

    The things I've struggling with has nothing to do with the scope, and everything to do with the fact I have absolutely no idea how to do elementary things because documentation is lacking in all our networking solutions. Well, with UNET it was also broken too when I used it (literally broken on release; I'm sure those bugs are gone by now though) but yea, those docs...

    Like I said, I don't find any other form of programming difficult because either

    • There's fantastic documentation on it
    • I can just easily figure it out using tried & true ways to program things & some nifty design/engineering thinking.
    • Other tools "Just Work" or are less complex & so the developer can fix bugs faster.
    I created several ways I could create a huge open world & send it to the Client from the Server. All of those ways would work, except I'd get stuck trying to do a single thing. One line of code, one function, that would fix the problem.

    That just would happen to me A LOT. Kindof like when I'd run into circular dependency problems when programming.

    Also to note, making a pong multiplayer game in FORGE is incredibly easy & takes a few minutes. The end.

    Hell, they even have an amazing looking action-shooter game that is fully networked. Easy stuff witih forge.



    It's when you step outside of the simple things that it immediately gets exponentially more difficult bc of the lack of docs/tuts.
     
    Last edited: Mar 21, 2016
  22. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Yea, great post & great points.

    My current project definitely "requires" it. Otherwise, I will end up adding multiplayer in an expansion because it will be the most demanded thing. I don't want to make the same mistake Project Zomboid made (swear there won't be multiplayer until release, then revamp the entire game mid-project to add multiplayer). Or Don't Starve (release the game & an expansion, then make a completely different game that is the same thing but worse, but with multiplayer, stunting future expansion growth & depriving consumers of 2 expansions in the process.)

    My current game...I guess it's most like Don't Starve, and a large part of my target demographic is "People who loved Don't Starve", among some other themes/games. If you followed that game, it was a singleplayer game up until their third "expansion", which was a multiplayer version of it. It made the game soooo much better, IMO, and was quite a popular expansion (I think). And what would minecraft be without multiplayer? And all these 3D survival games? They literally only exist BECAUSE of multiplayer. (DayZ, Rust, LiF, etc.)

    Plus I am making this game so me & my wife can play together, so I really wanted that multiplayer ;)

    I'm close! So close! And to be honest, it will definitely pay off. Even if I spent 120-200 hours total to implement multiplayer, that is a pretty amazing/big feature for such little development time. (Er, I say little, but if I took 3850 hours to make a game, that could be 3.1% to 5.2% total dev time, and who knows how much time it'll actually take, lol).

    Really though, 3% to 5% of dev time for multiplayer? Maybe I should re-title this thread "Think twice before NOT adding multiplayer! Do it! Do it!" after I'm done being frustrated, of course, lol :p
     
    tatoforever and Ryiah like this.
  23. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    I realized this exact thing right after I posted the OP. I knew if I didn't post that, everyone would be disappointed! :D
     
    Acissathar likes this.
  24. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363
    Also, adding a two-players-on-the-same-device mode can be helpful to try things out before going for a networking solution. But then you will have 3 modes which can lead to extra bugs!
     
  25. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    Granted, I come from a networking background but in general what you speak about isn't really unique to networking. It's just that with everything else (GI, animations, pathfinding, AI, etc.) you have had years of hardware advances that have by some sense built in making things easier at the expense of some inefficiency. This is very much where Unity is at when it comes to game development (it isn't the fastest but certainly is the quickest to learn for beginners).

    However, where everything local is using some of you many gHz clockcycles to make things easier and less bare to the metal, our internet connections still lag way behind. Yes its better than the days when speeds were measured in baud but its still orders of magnitude slower than everything else. When you combine this with the fact that data sizes for models, audio, etc. have gotten huge networking in anything real time (action games not solitaire) has to stay bare to the metal. Every bit and byte matters and you try to squeeze efficiency to the max like was done locally when all programming was done in assembly. Throw in the fact that depending on the protocol you use that things can fall into the abyss or come out of order and of course it will be challenging. There might not be many places left locally that require you be so low level but there are still some around, it's really just a function of if you need things to be that optimized.
     
  26. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,368
    Actually, if you architect well your code (eg: Not mixing up input with movement and animations/visuals) adding multiplayer with the right tool of course isn't that hard. If you use well the ECS pattern it will pay off a lot. You will write less code and they will be shareable among a huge amount of entities.
     
  27. Aiursrage2k

    Aiursrage2k

    Joined:
    Nov 1, 2009
    Posts:
    4,835
    Yeah its funny we added multiplayer to our game but almost no one played it, they are playing the single player campaign which we thought was a throwaway mode
     
  28. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    I started off assuming you were right, that it's not that unique to networking.

    Then you said all that; Sounds really unique to networking to me, haha.

    Really though, it's all about those networking tools. They just aren't up to speed and never have been. Not really sure why...other than most of them being almost sparkling new (UNET, Forge- both just came out. Bolt isn't that old either I don't believe.) Not sure what Photon's docs are like, but that's been around long enough that they have no excuse but to be excellent & thorough. But then again, people don't go around bragging about it so idk.

    It's not like the demand isn't really high for these types of assets. It's gotta be because they are "unique". Otherwise, why wouldn't we see a great one, like how he saw great GUI packages or great AI assets?
     
  29. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    This is exactly right when it comes to networking. The smaller shops and indie developers on this platform can't afford the overhead associated with having to "guess" at the right-way, or the backlash of getting it wrong. Networking has a HUGE backlash when you get it wrong, everything in this space is horrible when it goes bad.

    Unity needs to take it's resources, invest some time and money, come up with the RIGHT way to do it and tell their users.

    Also...yes, for god sake, let the networking stack do it's job and DONT send a stream of single bytes, that's an unbelievably bad way of doing it.

    So...question, is there a reason you're actually streaming content from your server like this instead of just streaming the request to instantiate it? Shouldn't all the resources be on the client already and you just need to tell it to load them? Or are you truly trying to send brand new resources to your game client that wouldn't exist at the time of the install or patch that must be sent in game?
     
    moco2k, Ryiah, hippocoder and 2 others like this.
  30. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    My world is procedurally generated upon the creation of the server & is extremely large. I need to send very simple data (ints, strings, some Vectors) for the Client to know what the world looks like. What objects exist & where they exist, what shape the world is in, etc.

    It's incredibly simple. Literally just a List<> of a custom class containing minimum amount of primitive data.

    I'm suppose to be able to just send a byte[ ] through via RPC or WriteCustom() in Forge. However it simply doesn't work. My RPC's work perfectly when I pass a string, int, or nothing. When I try to pass a byte [] or Forge's BMSByte? The client never receives the RPC. No errors, no messages, just nothing.

    So I'm just stuck here waiting for an answer as to why it isn't working. Can't find ANY documentation of how to do it outside of the WriteCustom tutorial/example which I copied exactly (but still does not work).

    And I'm not streaming the whole world. I eventually found a much more efficient method where the world not networked, but instead the Client makes a single request to load the world on connecting, then just using normal (working) RPC messages to update the world (delete/change objects, add new ones, etc).
     
  31. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    This is normal for indies. Because mp is the most competitive space in game development. Sony warned me about this so I'm going to trust them.

    You can't do a heavy mp game without enormous risk, but announcements like what MS did - sharing platforms can feed more players. Players aren't going play mp unless there's someone to play with so unless you nail that you get titanfall, and if it happens to AAA, it most certainly happens to indies big time.

    The key to getting mp to be successful lies gamifying progression in mp. That's easy to say, but it's not easy to pull off... first things first though - getting mp up and running :/
     
    Freakyuno likes this.
  32. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    Ok, thats actually one of the really good reasons to do exactly what you're doing.

    So, while not a long term solution, can you try converting your byte[] in to a base64 string and sending that down and seeing if that works, then you can convert it back on the client side?

    It's super easy to do, and pretty fast. Obviously not a long term solution, but may help you move on, and you can remove the base64 conversion when you get an answer or a better workaround.
     
    CarterG81 and GarBenjamin like this.
  33. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Thanks for this suggestion. Have no idea what base64 conversion is, so I'll have to look that up.

    What's strange is that if I send a byte like

    Code (csharp):
    1. byte[] = new byte[] { 3, 342, 23, 61, 23 };
    Then it works perfectly.

    It's when I convert my custom class into a byte[] that the client never receives the RPC.

    Serialize function
    Code (csharp):
    1.  
    2.   // Convert an object to a byte array
    3.   public static byte[] ObjectToByteArray(World obj)
    4.   {
    5.   Debug.Log("ObjectToByteArray()");
    6.  
    7.   BinaryFormatter bf = new BinaryFormatter();
    8.   using (var ms = new MemoryStream())
    9.   {
    10.   bf.Serialize(ms, obj);
    11.   return ms.ToArray();
    12.   }
    13.   }
    14.  
    My custom class
    Code (csharp):
    1.  
    2. using System.Collections.Generic;
    3. using System;
    4.  
    5. [Serializable]
    6. public class World
    7. {
    8.   public List<TileData> WorldTiles = new List<TileData>(); //Collection of all tiles.
    9. }
    10.  
    11. [Serializable]
    12. public class TileData
    13. {
    14.   public myVector3 myPosition = new myVector3();  //Tile's Transform.Position
    15.   public myVector2 tilePosition = new myVector2(); //Tile's TilePosition
    16.   public string myName; //Name of Prefab to load (What Tile type?)
    17.   public string myBiome; //Biome the Tile belongs to
    18.  
    19.   public List<ObjectData> myObjects = new List<ObjectData>(); //A list of all the Tile's objects.
    20. }
    21.  
    22. [Serializable]
    23. public class ObjectData
    24. {
    25.   public myVector3 myPosition = new myVector3(); //Object's world transform.position
    26.   public string myName; //Name of Prefab to load
    27.   public string objectGUID;
    28. }
    29.  
    30. [Serializable]
    31. public class myVector3
    32. {
    33.   public float x;
    34.   public float y;
    35.   public float z;
    36. }
    37.  
    38. [Serializable]
    39. public class myVector2
    40. {
    41.   public float x;
    42.   public float z;
    43. }
    44.  


    What works / doesn't work
    Code (csharp):
    1.  
    2.    //WHAT WORKS
    3.   //byte[] newBytes = new byte[] { 20, 61, 23, 34 };
    4.   //myBytes = newBytes;
    5.  
    6.   //DOESNT WORK (Serializes without erorr but Client never receives RPC. No errors, no messages, just nothing.)
    7.   myBytes = ObjectToByteArray(MasterWorld.theWorldData);
    8.  
    9.  
    10.   //Forge functions. Works unless it's my custom class converted to byte[]
    11.   cachedData.Clone(Serialize());
    12.   Networking.WriteCustom(CUSTOM_ID, Networking.PrimarySocket, cachedData, true); //Forge WriteCustom function
    13.  
     
  34. Aiursrage2k

    Aiursrage2k

    Joined:
    Nov 1, 2009
    Posts:
    4,835
    I think it's still worth adding it anyway because if it's a hit that's only going to be a multiplying factor, but I guess you want to make sure the single player is good enough that if there is no multiplayer scene it can still sell. For example we are working a car combat game and it's not that fun playing against bots, we could still improve the single player experience to make it more enjoyable since that was not our focus at all, but if it was a dual stick shooter where the games already fun then adding multiplayer is going to just be icing
     
  35. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    @Freakyuno

    Tried converting to string. Failed to receive RPC, still.

    Client never receives RPC using that method.
    Code (csharp):
    1.   byte[] worldDataByteArray = ObjectToByteArray(MasterWorld.theWorldData);
    2.   string s = Convert.ToBase64String(worldDataByteArray);
    The below works perfectly. Client receives RPC. It's something wrong with my custom class turned into byte[].
    Code (csharp):
    1.   string s = "Test";

    Maybe my custom class is too large to send over the network?
     
  36. greggtwep16

    greggtwep16

    Joined:
    Aug 17, 2012
    Posts:
    1,546
    Only within games, there are some places that are still very commonly close to the metal. Operating Systems and most things in the embedded world come to mind off the top of the head. Within games while you can still go that low level if you want to, you usually don't unless it is along the critical path and you need the efficiency.

    Vastly overgeneralizing, but IMO there will never be a one sized fits all networking library (read never as until large fiber networks go everywhere and everyone has more bandwidth than they know what to do with).

    While on the face of the problem it may seem like there should be these great 3rd party libraries that make it easy, the reality is that everyone's games requirements are different and different traffic types require different solutions to compensate for the slow and less than ideal throughput of everyone's internet pipes. The main problems that I see are as follows.

    1. You essentially want to hit a sweet spot with packet size. Depending on the protocol used if you send a tiny packet the overhead is enormous (send a 1 byte message and the overhead will be over 10 times the payload and some protocols approaching 50 times the payload). Can't be too big either if the packet is over the MTU and on the internet the "safe" MTU is usually 512 bytes. Sure you can tell the interface to send bigger but really it's going to get broken up for you. Ideal packet size is going to have a big impact on your scalability as you get more players. You also don't want to get too fancy with wasting CPU with packing everything super small or using compression algorithms because in general you are doing this every frame for an action game.

    2. You want to hit a sweet spot with message frequency. Go too fast and you're increasing the chances that they'll come out of order or perhaps that you are saturating the weakest link on the pipe and actually decreasing your throughput. Go too slow and you'll need network prediction and other algorithms or guesses on where something actually is at a given time. Generally, there is always this trade off on how many messages and how long to hold the packet for before sending them all inside one packet. This totally depends on your game and can vary widely from game to game.

    3. If your data requirements exceed the realistic limitations of both of the above then your left with how you split the problem into more bite sized chunks. The most obvious example to this is open world games. Perhaps for your game it makes sense to split it up geographically. You then get into how to hand off players from server to server, how to load balance the backend, etc. Again the exact requirements will vary drastically from game to game, some just care about the players, other's keep state on destructible environments, etc. These require different tradeoffs to occur.

    You might think that these can be achieved with some sliders on packet size, message frequency, etc. and to a limited extent it can be but really this is tightly coupled to your game and it's requirements. Not to mention the sliders would tend to fight with eachother since packet size probably depends on your message frequency and vice versa. Many cases giving custom logical thought and combining many techniques tends to give the best results (and best results in networking tends to mean it's finally acceptable to the user). A little bit of packing data, a little bit of holding to send a larger packet, a little bit of sending not as fast as you want, and a little bit of algorithms on the other side for predicting "guessing" where other people actually are, etc.

    If there ever becomes a 3rd party tool that provides all of this in an easy to configure way, I think it will be the best selling thing ever in game development. Heck, the current tools are better than nothing and already sell well.
     
    tatoforever likes this.
  37. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    I think you're not closing your stream before you're returning it, which could be causing your serializer problems.
    Code (CSharp):
    1. // Convert an object to a byte array
    2.   public static byte[] ObjectToByteArray(World obj)
    3.   {
    4.   Debug.Log("ObjectToByteArray()");
    5.   BinaryFormatter bf = new BinaryFormatter();
    6.   using (var ms = new MemoryStream())
    7.   {
    8.   bf.Serialize(ms, obj);
    9.   ms.close();
    10.   return ms.ToArray();
    11.   }
    12.   }
    13.  
    It's been a while since I've worked with one like this, so I may be remembering incorrectly.
     
  38. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Well yea, of course. This thread isn't to go into extensive detail about network programming, thus keeping it brief is kindof a requirement :confused:

    I never mentioned that there needs to be. I mentioned that there doesn't seem to be ANY network library that fits ANY size. (One with Quality Documentation, anyway). Then again they're nearly all new, so I guess that's the main reason why. I just don't understand why there isn't a high quality asset for networking like there was for GUI (ex. NGUI, before the new Unity UI, Behavior Designer for Behavior Tree AI, etc.)


    Yea, you're definitely right about that. That's why I am at a loss why there isn't anything even close to that up until recently. The only non-new networking solution I even know of (that is Unity-native) is Photon and around that same time I believe two others... SmartFox something & ....a third one. All very similar.
     
  39. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    That would be embarassing, but it would make sense because I just copy/pasted this in a lazy moment from StackExchange. (Shameful, I know, and the only time I've ever done that, but I figured this would be safe since it's so incredibly simple. I felt uber lazy having already exhausted myself failing to do this "one thing" so I thought "What could go wrong? It's just serializing an object.")

    edit: Oh, I already tried this earlier & nothing changed @Freakyuno

    Code (csharp):
    1.  
    2.   // Convert an object to a byte array
    3.   public static byte[] ObjectToByteArray(World obj)
    4.   {
    5.   BinaryFormatter bf = new BinaryFormatter();
    6.   MemoryStream ms = new MemoryStream();
    7.   bf.Serialize(ms, obj);
    8.   return ms.ToArray();
    9.   }
    10.  
     
  40. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    I could be equally embarrassed by providing a really simple solution that doesn't work. There is however two issues there.

    1.) You shouldn't generally return from inside a using statement. It's kind of a bad "closure" practice. Declare your variable outside the using statement, assign it inside the using statement, and then return it below.

    2.) Streams can be unpredictable when used without closure, but it should have been ok cause you were calling a function on it (the .ToArray() ) which should force it to close.

    But give it a shot and let me know.
     
    CarterG81 likes this.
  41. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Thanks for the tip. I'm thinking I might just try an idea similar to the idea Darkhog suggested. Maybe instead of sending the entire World (a list of Tiles) I should just try to send one tile (which will be a lot smaller in size.) Idk why, but I have the feeling it's either a freak problem serializing or it's just too big in size to send using Forge.
     
  42. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Looks like I was right. I serialized & sent a tile "TileData" custom class and it worked flawlessly.

    When I try to send my "World" custom class, since it's a 55x55 collection of "TileData", it just never gets received by the Client for some reason. (Too big?)

    Thanks @darkhog , your suggestion helped me to figure out a temporary solution until I can get in touch with the Forge developers.
     
    darkhog likes this.
  43. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Nevermind, it can't be because it's too big. My test scene is only a 3x3 tilemap with only 28 items in the world. Incredibly small.

    However, if I send just one TileData, it works. Client receives RPC correctly & everything.
     
  44. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    That probably just means it's having trouble serializing the list of tile data at this line:

    public List<TileData> WorldTiles =new List<TileData>(); //Collection of all tiles.

    Try throwing another dummy property in there and setting it, and commenting out your tile data and see if it'll go, then add a single tile inside world data instead of a list and see if it'll go.
     
    CarterG81 likes this.
  45. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    If it is size related there is a good chance it is not a matter of too much data to send (unless Forge or whatever actually has some limit) and instead the data is being split up across multiple packets that are not being correctly appended together on the other end. That's just a guess because it does seem like when you send a small amount of data it works fine. Likely packaged into a single message packet.

    What does the code on the receiving side look like? How are you marking the end of a transmission so you know when the last bit of data of a large message has arrived or does Forge handle that automatically? Another thing is when sending small amounts of data quickly like say 3 messages back to back you cannot rely on those actually coming in as 3 separate packets on the receiving side. There is a very good chance that data will all come in a single packet or even in 2 packets.

    EDIT: Well I just saw your post about it only being 28 bytes which is certainly a small amount of data so perhaps multi packets are not happening.
     
    darkhog likes this.
  46. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    If I change it to

    Code (csharp):
    1.  
    2. [Serializable]
    3. public class World
    4. {
    5.   //public List<TileData> WorldTiles = new List<TileData>(); //Collection of all tiles.
    6.   public int number;
    7. }
    It definitely works.

    I also tried

    Code (csharp):
    1.  
    2. [Serializable]
    3. public class World
    4. {
    5.   //public List<TileData> WorldTiles = new List<TileData>(); //Collection of all tiles.
    6.   public List<int> number;
    7. }
    Also works.
     
  47. FisherM

    FisherM

    Joined:
    Dec 28, 2013
    Posts:
    366
    Good thing this wild Forge Networking Developer is showing up to save the day. ;)
     
    CarterG81 likes this.
  48. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    edit: Nevermind. Problem still persisted, I forgot to comment back in the line of code that populated my custom class with data :p

    And within minutes, BAM! Instant solution & 100% working.

    "If only I had that experience too!"

    Thanks sooooooo much!

    10/10 will throw fit again.​
     
    Last edited: Mar 30, 2016
    Martin_H likes this.
  49. FisherM

    FisherM

    Joined:
    Dec 28, 2013
    Posts:
    366
    "10/10 will throw fit again."

    I was worried you'd say that :p
     
    CarterG81 likes this.
  50. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Really, it's just bc I love all the fun pictures. Any excuse to sift the web to throw a picture party

     
Thread Status:
Not open for further replies.