Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Nominations have been announced for this years Unity Awards. Celebrate the wonderful projects made by your peers this year and get voting! Vote here!
    Dismiss Notice
  6. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

[NO CCU LIMIT] Forge Networking now OPEN SOURCE

Discussion in 'Assets and Asset Store' started by farrisarts, Dec 22, 2014.

  1. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    Ok, your code worked. I am not sure why, I was calling the Networking.SetPrimarySocket. But I am still having problems with my project. I am going to put it to bed now and have a fresh go at it tomorrow.

    At this stage, it looks like something in my code logic. I'll let you know what I find.

    Thx again for your help.
     
  2. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Sorry, I should have pointed out the issue.

    So you do this block of code on the awake before you called the connect method:

    Code (CSharp):
    1. if (Networking.PrimarySocket == null)
    2.     Networking.connected += Setup;
    3. else
    4.     Setup();
    At the point that this is called, since it is before the connect, the Networking.PrimarySocket is null. So when you register an event to that null object (or one that already exists that is about to be overwritten) it doesn't register it properly.

    No problem! :D Let me know if you have any other questions.
     
  3. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    I have an idea for a feature that could be really useful for adding single player functionality to the multiplayer game. Could there be an 'offline mode' where all data is routed back to yourself as if you were the server instance? This way, players could play a single player game when maybe their internet is down or they want to test things out. Making a new set of scripts for single player would also work but having an offline mode would keep everything flexible and covered by one implementation of Forge.
     
  4. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    This is a great idea. If you were allowing clients to host servers then they could start a server instance and not notice the difference. However, currently, if you try a connect as a client (because they can't host) then they would not be able to run very easily. I will add a ticket for this feature request, it is a really good idea! :D
     
  5. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    I think I got this right....

    If you don't add a AddCustomDataReadEvent to the networker and you call WriteCustom, it gives the dictionary error.

    If you run the code below, you should be able to replicate?

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using BeardedManStudios.Network;
    5.  
    6. public class ForgeExample_WriteCustom : MonoBehaviour
    7. {
    8.     public string id = "MyClassThing_01";
    9.  
    10.     public int num = 0;
    11.     public bool buul = false;
    12.     public float money = 3.1f;
    13.     public string first = "brent";
    14.     public double big = 0.0000004;
    15.     public Vector2 v2 = new Vector2(5, 13);
    16.     public Vector3 v3 = new Vector3(9, 133, 123);
    17.     public Vector4 v4 = new Vector4(1, 3, 34);
    18.  
    19.     private BMSByte cachedData = new BMSByte();
    20.     private NetWorker socket;
    21.  
    22.     private void Setup()
    23.     {
    24.         Debug.Log("Setting up Primary Socket");
    25.         Networking.SetPrimarySocket(socket);
    26.  
    27.         Debug.Log("Registering read callback event");
    28.         //Networking.PrimarySocket.AddCustomDataReadEvent(id, ReadFromNetwork);
    29.         //socket.AddCustomDataReadEvent(id, ReadFromNetwork);
    30.     }
    31.  
    32.     void Awake()
    33.     {
    34.         socket = Networking.Connect("127.0.0.1", 15367, Networking.TransportationProtocolType.UDP, false);
    35.  
    36.         if (socket.Connected)
    37.             Setup();
    38.         else
    39.             socket.connected += Setup;
    40.     }
    41.  
    42.     private void Update()
    43.     {
    44.         if (Input.GetKeyDown(KeyCode.Space))
    45.         {
    46.             num = 9;
    47.             buul = true;
    48.             money = 100.53f;
    49.             first = "Farris";
    50.             big = 214324.3533;
    51.             v2 = Vector2.one * 5;
    52.             v3 = Vector3.one * 9;
    53.             v4 = Vector4.one * 2.31f;
    54.  
    55.             cachedData.Clone(Serialize());
    56.             Debug.Log("WriteCustom");
    57.             Networking.WriteCustom(id, socket /* Networking.PrimarySocket */, cachedData, true);
    58.             Debug.Log("WriteCustom 2");
    59.         }
    60.     }
    61.  
    62.     private BMSByte Serialize()
    63.     {
    64.         return ObjectMapper.MapBytes(cachedData, num, buul, money, first, big, v2, v3, v4);
    65.     }
    66.  
    67.     private void ReadFromNetwork(NetworkingPlayer sender, NetworkingStream stream)
    68.     {
    69.         Deserialize(stream);
    70.     }
    71.  
    72.     private void Deserialize(NetworkingStream stream)
    73.     {
    74.         num = ObjectMapper.Map<int>(stream);
    75.         buul = ObjectMapper.Map<bool>(stream);
    76.         money = ObjectMapper.Map<float>(stream);
    77.         first = ObjectMapper.Map<string>(stream);
    78.         big = ObjectMapper.Map<double>(stream);
    79.         v2 = ObjectMapper.Map<Vector2>(stream);
    80.         v3 = ObjectMapper.Map<Vector3>(stream);
    81.         v4 = ObjectMapper.Map<Vector4>(stream);
    82.     }
    83. }
    84.  

    Call stack:
    Code (csharp):
    1.  
    2. KeyNotFoundException: The given key was not present in the dictionary.
    3. System.Collections.Generic.Dictionary`2[System.String,System.UInt32].get_Item (System.String key) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
    4. BeardedManStudios.Network.NetworkingStream.PrepareFinal (BeardedManStudios.Network.NetWorker socket, IdentifierType identifierType, UInt64 behaviorNetworkId, BeardedManStudios.Network.BMSByte extra, NetworkReceivers receivers, Boolean bufferedRPC, System.String customidentifier)
    5. BeardedManStudios.Network.NetworkingStream.Prepare (BeardedManStudios.Network.NetWorker socket, IdentifierType identifierType, BeardedManStudios.Network.SimpleNetworkedMonoBehavior networkedBehavior, BeardedManStudios.Network.BMSByte extra, NetworkReceivers receivers, Boolean bufferedRPC, System.String customidentifier)
    6. BeardedManStudios.Network.Networking.WriteCustom (System.String id, BeardedManStudios.Network.NetWorker netWorker, BeardedManStudios.Network.BMSByte data, Boolean reliableUDP, NetworkReceivers recievers)
    7. ForgeExample_WriteCustom.Update () (at Assets/Bearded Man Studios Inc/Networking/Examples/Write Custom/Scripts/ForgeExample_WriteCustom.cs:56)
    8.  
    9.  
     
  6. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    I finally worked it out why I was getting the Dictionary error in my code :D:D:D:D

    You must have a AddCustomDataReadEvent for the ID you want to send through WriteCustom.

    In my project the ID's sent from the client are different to the ID's sent from the server. eg: Client will send server "spawnMe", server will send back "spawnPlayer". So in my project the ID's I was sending were not known to the networker. I guess the work around for now is to load client and server ID's on client and server networkers.

    Does this mean that when I call WriteCustom, you are converting my string ID to an index? if so, how do you ensure the index's match on both client and server? do you have to AddCustomDataReadEvent in the same order on both sides?

    Is it possible to change this so I don't need a corresponding AddCustomDataReadEvent for each ID I want to send through WriteCustom?
     
    Last edited: Feb 5, 2015
  7. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Oh wow! That is an illusive bug! They should be mapped 1:1 on both the client and the server, if they are not, then the mapping system must have a bug. D:

    Thanks for looking into this! We will work with the code you provided as well as look and see what this bug could be for the mapping job.
     
  8. ddtxwd

    ddtxwd

    Joined:
    Oct 29, 2012
    Posts:
    3
    I used photon for a long time , now i want to try Forge.
    sign me up for beta testing please.
     
  9. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    Hi Brent/Brett,
    I would like to stabilize my code and I need to decide if I use the Write, WriteRaw or WriteCustom.

    The critical features I need are:
    - Send a byte array (i.e. my code handles serialize/desialize classes & maybe compression)
    - Can be sent to a specific player or broadcast to all players (i.e. Server can send game state to a new player when they join)
    - Supports unreliable and reliable UDP

    WriteCustom has all the features I need, but it has some extra baggage and might be a bit heavy
    WriteRaw is nice and lite weight, but it doesn't support NetworkingPlayer or ReliableUDP parameter
    Write, supports NetworkingPlayer however there is mismatch between Beta 10 and Doco, when you use Networker.Write in code it has no option for Reliable UDP, but doco indicates it should?

    Also, Write is the only method that does not use BMSByte. So, is this method going to be supported in the future and if so, will you bring it into line with WriteRaw and WriteCustom and use BMSByte?

    WriteCustom meets my needs. But I would like to know what the road map is for Write and WriteRaw, eg: Would you consider adding NetworkingPlayer and Reliable UDP as optional parameter's in WriteRaw?

    Also, so I don't have to test to find out, are the following features now complete?
    - NetworkingPlayer parameter on Write and WriteCustom
    - Reliable UDP parameter on WriteCustom
    - Networker.Me
    - Networker.Players
     
  10. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    WriteRaw is perfect right now! It's supposed to be as minimal as possible so you can implement your own NetworkingPlayer or reliable transmission. As for the other behaviors, I think they should offer all the needed functions as adding them in customly would create more overhead because everything is already serialized, etc..
     
  11. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    Thats cool. Sounds like WriteRaw is perfect for your needs.

    I am just asking the question so I can decide how to structure my solution. For my purposes, WriteRaw is too expensive. From the server If you only want to only send the message to one player, then you wouldn't use WriteRaw because it will blast every player with that message. Sending every message to every player is wasting a lot of bandwidth. If you are writing a FPS or an MMO you wouldn't use it because it is too wasteful. Having a player parameter on WriteRaw so you can target a specific user, would make it very very efficient for all genre of games

    Note, the target player should not be sent in the UDP packet, it is only an address Forge uses to address the message. Alternatively It could also be a collection so you can send messages to a group of players, eg: team messages.

    Brent & Brett are doing a fantastic job of listening to all the requests that have been thrown at them and walking that tightrope of designing a solution that is functional/feature rich but not too complicated and can be used for all genre of games.
     
    Last edited: Feb 5, 2015
    farrisarts likes this.
  12. Cranick

    Cranick

    Joined:
    Nov 20, 2011
    Posts:
    305
    Please send an email to support@beardedmangames.com and we will assist you there. :)
     
  13. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Perhaps we can make it so that the server can do a WriteRaw to a particular player? Would this feature help on this issue?

    Oh! I guess that answers that! I will make a ticket for it! :D

    This actually sounds like a big AWESOME system we can create in the engine. So I'm thinking that we will make a "group" functionality where the server can match particular clients together as a group. I will need to add in some functionality so that you can move players around within the groups. I will get started on designing this kind of system, I would love to have this feature myself :D. Then messages could be sent to a group id and only that group of players will receive it :).

    Thank you very much. We are doing our best to make just that kind of system. We are wanting a very feature rich system for developers, yet incredibly flexible and extendable, however making the bare use of it so simple that people who have never developed networked games in their life could pick it up and run with it and really learn networking along the way :)
     
  14. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    It could be very well possible that a combination of these could solve the issues as well.

    Custom compression might be best done in WriteRaw, as stated we will add the ability to write to particular players to save overhead as well.

    True, this one is bare bones and has only a 1 byte header for routing purposes. Since this is the only header we have in this one it is impossible to implement our standard reliable UDP system into this one. A light weight R-UDP could be devised. We may look into making a WriteRawReliably function which will have a 16 byte header so that it works with our reliability system. Of course this header byte count could be lowered if there was a different R-UDP system devised just for WriteRaw and we didn't hook into our current subsystem.

    BMSByte could possibly be an override for Write. Write was basically originally designed to be a bare bones out of the box solution for simple data transfer. It is pretty powerful in its current state and I think we can squeeze some extra power out of it by including the passing of our caching system (BMSByte).

    WriteRaw may be at the end of its design rope as it is really a function for developers to make their own transportation layer of bytes if the built in one. We may make some new middle ground functions to wrap up things like reliable transfer so developers don't have to worry about that as well as player identification.

    Working and tested (I think the last test was around Version 9), by passing a player the message will only be sent to that user.

    Input and working but not heavily tested

    Recently fixed in 9.x I believe. Should be working fine, tested but not heavily

    This is working and heavily tested server sided. The client can actually get a list of players by requesting them from the server using the NetworkingManager poll function. Then the NetworkingManager Players field will be populated with the players.
     
  15. Cranick

    Cranick

    Joined:
    Nov 20, 2011
    Posts:
    305
    Thank you, glad to make it easier for all of us developers that want a great networking solution. :)
     
  16. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Hello all! I know that you have all been spoiled by the daily updates and are now asking where the update was yesterday. So I thought I would send out a message on the forum to give an update.

    We have been working very hard on some of the new, core, ground breaking features to the system. We have had very good results thus far and will be having a working Beta for them very soon. The system is ever growing as our community is! :D We can't wait to release the new Beta's for the system and we can't wait to get your feedback and bug reports. The Forge empire of software is expanding fairly large and we are doing our best to keep a very controlled designed and manageable environment. We care about every system in Forge equally and will be working hard on every system to make them valuable, exciting, powerful and simple.

    Also we should be releasing another bug fix update soon for the found bugs :)
     
    Last edited: Feb 6, 2015
  17. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Oh wow, sorry for talking before knowing. Yeah, being able to target specific players and the server would be very useful.
     
    Zaddo67 likes this.
  18. Neo-Gamefactory

    Neo-Gamefactory

    Joined:
    Oct 18, 2012
    Posts:
    141
    I have one question :)

    When i host a game with

    Code (CSharp):
    1. Networking.Host(......);
    is it available on all three ways?

    Localhost : 127.0.0.1
    private IP (LAN)
    public IP (Online)

    ?

    Because i want to use your Framework in our Project "Oncoming Death" that is greenlit on steam :)
     
    Last edited: Feb 6, 2015
  19. Neo-Gamefactory

    Neo-Gamefactory

    Joined:
    Oct 18, 2012
    Posts:
    141
    AAAAAND :D

    I started the Tutorials on my Channel with the Intro, how fast it is to integrate Multiplayer in Unity3D with your Asset :)



    I hope you like my tutorials that i will release soon :)
     
    jpthek9 likes this.
  20. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Yes, it is available for all three. :)

    We are actually also almost done with a few addons to the system, one of which is LAN discovery. So if you are on the Local Network it can automatically find the server that is being hosted and connect to it. No need to get the other persons local ip.
     
    Neo-Gamefactory likes this.
  21. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Awesome tutorial! Yes, I like them, they are simple and easy to understand :).

    We will be adding developer created tutorials to our website as well, if you guys don't mind? :D
     
  22. Neo-Gamefactory

    Neo-Gamefactory

    Joined:
    Oct 18, 2012
    Posts:
    141
    Haha xD this Video wasn't a tutorial :D

    It was only a intro to my New "Forge Networking" tutorial series ;)

    also i wanted to Show how easy it is with Forge :)
     
  23. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    XD Pardon my ignorance.

    I swear I can read (sometimes)! haha

    I like it :) It was, as I stated, easy to follow what was going on and see it's ease of use. I can't wait to see how the series comes out. Hopefully we will see many series from developers as there are so many different kinds of games that networking can be made for. I am super anxious to see how they all turn out! :D
     
    Neo-Gamefactory likes this.
  24. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    I've been wondering what the pricing for the Cloud will look like by the final release. Will it be calculated based on DAU, CCU, or bandwidth? Also, at what rate? Forgive me for this, but I'm thinking of integrating Forge with PlayFab because they would synergize very well (and you guys made it too easy with the flexible plugin system).
     
  25. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    We actually are just about done with our Beta for accounts, user login, user registration, currency, premium currency, and currency tracking. After this releases to beta we will be working on our cloud storage api which will give developers the ability to save data to a database that we host. We believe that DAU and CCU pricing is EVIL! We believe that pay-as-you-go pricing is fair and suits developers needs for both huge studios and small indie studios. Since it is likely that indie studios won't be hammered by users 100% of the time then they should only have to pay for what they use! Why hasn't this model already been used? Simple, pretty much every other cloud gaming provider in networking out there believes that they want your extra cash for something you don't use. This is extremely unfair and un-appealing to those who know how to do simple mathematics.

    For our hosted accounts, currencies, and data we will be doing bandwidth based pricing (this will include the cost of CPU that we will be paying for ourselves), so there will be only 1 fee in these cases which is bandwidth, no CCU no DAU, just easy bandwidth usage.

    When we release cloud based game hosting, this will work much the same except there will be some math we will need to do in considering the CPU cost we will need to take.

    So for the Backend-As-A-Service (BaaS) (user logins, data, and such) there will be 1 bandwidth usage cost; however for cloud based game hosting it will be bandwidth cost + CPU mathematics. We will do our best to make this as simple as possible (usage calculators and such)! By providing usage based costs to developers, that means as we grow and our prices lower for quantity usage, then the price for usage to our developers can scale down with our costs as well! :D

    Also note, there are some secret things we will be providing coupled with what was talked about here. They are going to be pretty huge and we can't wait to reveal them to everyone but for now, just know they are coming :)

    No forgiveness needed, it is a very valid question to be asking! :D

    Also, though we are going to provide these services which will dispose the need for PlayFab, we highly encourage anyone to integrate with whatever system they wish! We are happy to have our system cross link between other well known service providers. If you do make this plugin, you may even consider sharing or selling it to those who have their backend on PlayFab and wish to use Forge as their base networking library but still keep their integration with their current BaaS provider.
     
    Last edited: Feb 7, 2015
    jpthek9 likes this.
  26. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    This sounds awesome! I also think DAU and CCU pricing is evil and paying by bandwidth makes the most sense. I'll wrap up the integration and run a test on PlayFab. I might not use it at all given the plans for Forge but it's nice to extend the frontiers of this library and bring world peace (easy integration) to all. Also, thank's for not seeking profit as the main priority. Making enough money to put food on the table is important but putting the customers' interest before everything is extremely admirable.
     
  27. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    I just found a bug with trying to connect without a server instance. For some reason, this crashes my editor the 2nd time I try to connect and prevents the server from being started until I call Networking.Disconnect() on that client.
     
  28. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Awesome! Hopefully the ability to integrate with PlayFab will bring in new users who are currently locked into other systems because PlayFab is what they know/have. :) I am very open to our system being used with other systems if that is what developers wan't/need and hopefully that will help expand our community.

    I firmly believe that profit is not what is important in a product. Ease of access, easy to use, easy to integrate, power, and flexibility are what make a good product. Our #1 goal is to provide these poins :D
     
    jpthek9 likes this.
  29. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Woah! I'll add this to a top priority to debug. Sounds like a thread is kept loose in the wild when the Networking.Disconnect doesn't happen. I'll make sure to resolve this asap!
     
  30. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Could you clarify on how to read data from the bare metal server? The Execute from IPluginReadRawData doesn't seem to be called. Just to confirm, is this supposed to be triggered when I use NetWorker.WriteRaw()?
     
  31. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Last I tested, this should be working. So you are implementing
    Code (CSharp):
    1. void Execute(NetWorker netWorker, BMSByte data);
    and it is not working? Not even a log? If not I'll check this out as soon as I get home!
     
  32. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    I know it's sending from the client but not printing or doing anything on the console. Here's my code in case I'm doing anything wrong.

    For the server. Nothing prints at all.
    public class ReadRaw : IPluginReadRawData
    {
    public void Execute()
    {
    BMSConsole.WriteLine("received!");
    }
    public void Execute(NetWorker netWorker, BMSByte data)
    {
    string message = string.Empty;

    for (int i = data.StartIndex(); i < data.Size; i++)
    {
    if (i != data.StartIndex())
    message += " ";

    message += data.byteArr.ToString();
    }
    BMSConsole.WriteLine("received!");
    BMSConsole.WriteFromThread(message);
    }
    }

    For the client. Prints every time.
    void FixedUpdate()
    {
    BMSByte bit = new BMSByte();
    bit.byteArr = new byte[]{1,2,3,4};
    peer.WriteRaw(bit);
    print ("writ");
    }
     
  33. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Awesome, thanks for the code sample. I'll use then when I do my testing tonight. We'll upload a new Beta with the fix when we find it.
     
  34. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Hello there! I tested out this code and it seems to work fine. Did you put your compiled plugin into the AutoLoad directory in the plugins folder or just the Plugins folder? If you placed it in the plugins folder then you will need to load it with "loadplugin MyPluginName". If you want to load it from start then you will need to drop your plugin into the AutoLoad folder.

    If you did do all of this and it is still not working. Would you mind sending me a .zip via email of your sample that isn't working?
     
  35. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
  36. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Awesome thank you. I will check to see if Brett received it :)
     
  37. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Oh sorry! I just grabbed the email I was seeing that was sending the versions. I'll send the link to support@beardedmanstudios.com as well (I'm not completely sure what your email is.. is it brent@bms.com?).
     
  38. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
  39. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    I had a bug in my code with Networker.Connected not being set to true.

    The problem was due to calling AddCustomDataReadEvent from my Networker.connected event handler. It was crashing because AddCustomDataReadEvent must be called on the main thread. This impacted the internal Forge code because Connected was now never set to true.

    So I tried to use CallOnMainThread. This didn't work. The event handler delegate() function got called. But main thread delegate never got called? Is there anything wrong with my code below?

    So, I wrote my own CallOnMainThread manager. Problem solved, now works.

    IMHO, Forge events should only be fired on the main thread. i.e. when Networker.connected gets fired, it should be called on the main thread.

    I can see some advantages for event handlers being called on a worker thread, if you want to take advantage of threading. But not much can be done on a worker thread inside unity. Perhaps the solution is to have 2 events, Networker.connected, gets called on the main thread, Networker.connectedWorker gets called on the Forge networking worker thread.

    I just think that unless you know a little about how threads work and delegates, naive coders will get tripped up very easily when using Forge events that are being fired on worker threads.

    Code (csharp):
    1.  
    2.                 socket.connected += delegate()
    3.                 {
    4.                     NetworkingManager.Instance.CallOnMainThread(delegate(object[] args)  '<-- Got called
    5.                    {
    6.                        ServerConnected(); '<-- Never got called
    7.                     }, null);
    8.                 };
    9.  
     
    Last edited: Feb 8, 2015
  40. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    I agree 100% with adding main thread events. I too have tripped up with doing things on the thread when it was expected on the main thread because Unity engine objects need to be processed on the main thread. I think that adding the event load to the main thread will also free up some extra processes that need to happen.

    I will be moving the events to work on the main thread as I think 60%+ of the time I need them to run on the main for Unity as well. We will make this primary then open up threaded events in the future once again for more power users.

    This looks correct, we have used CallOnMainThread quite a few times without issues. I will assess this issue, it could have something to do with other parts of the threading system. First I will be putting a release for the events on the main thread as I believe that is critical!

    Thank you very much for this super useful feedback! We will start with the events that do not hold references to objects and work our way down from there.

    EDIT: I have found the issue with our CallOnMainThread. This happens only on startup. This is being addressed now!
     
    Last edited: Feb 8, 2015
    Zaddo67 likes this.
  41. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Hello all, we are pushing out a package tonight. We are still working on some of the website stuff and have it almost ready for Beta.

    In the package tonight you will find the following:
    1) LAN Discovery
    2) Connect and Disconnect events are called on main thread
    3) CallOnMainThread now works on Awake methods when a scene is loaded
    4) WriteRaw now supports sending to a targeted player
     
    Last edited: Feb 8, 2015
    jpthek9 likes this.
  42. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    Hi Brent, From your earlier email you indicated that the string ID used in AddCustomReadEvent, is converted to a byte by Forge, for transfer. How does Forge synchronize these ID's on all systems. Or, is it up to the developer to ensure that the AddCustomReadEvent's are executed in the same sequence on all clients and server?
     
  43. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    We actually need to audit this system as it should be mapped internally and tracked. However, we do have a ticket opened for it because it may be getting out of order in the system. If we do have a bug and our mapper is not in place, then Unity's script execution order is in control of making sure they are in order and that is bad (because of dynamic instantiation and communication latency).

    We will be auditing this system and will make sure that the server is in control of relaying the order of these. However, if your objects are registering this information at start (and not dynamically) it should be workable until we get the fix in place if so.

    Have you ran into any issues with this?
     
  44. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    488
    I don't think so. I was just chasing down a few gremlins and wanted to check on how this works.
     
  45. zapoutix

    zapoutix

    Joined:
    Jan 2, 2015
    Posts:
    43
    Hi guys,

    I was not available for a while, and it seems you did huge progress.

    Cannot wait to test the latest beta ;)
     
  46. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Awesome, welcome back! We can't wait to have you back testing out the Beta and finding bugs and requesting features XD. :)
     
  47. Neo-Gamefactory

    Neo-Gamefactory

    Joined:
    Oct 18, 2012
    Posts:
    141
    Is it possible to Instantiate a GameObject without the NetworkManager? I don't want to use it, because this array in the Manager...
    If i have 100 Objects then i must attach it all to this manager and this to much... i want to instantiate it manually like this.

    Code (CSharp):
    1. public GameObject objectToInstantiateFromHierachy;
    2.  
    3.  
    4. ........
    5.  
    6. Networking.Instantiate (objectToInstantiateFromHierachy, .....)
    7.  
    8.  
    9. .....
     
  48. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Woah! You have just made me realized that there is a bug D:. I we will send out a hot fix for this.

    After Fixed:
    So, basically the Networking Manager can specify a folder in the resources directory to spawn objects as seen here:
    upload_2015-2-8_12-27-26.png


    This will correspond with a Resources sub directory:
    upload_2015-2-8_12-27-31.png

    Then you can call the Networking.Instantiate without assigning the object into the array:
    Code (CSharp):
    1. Networking.Instantiate("Spawn", NetworkReceivers.All);
    Note:
    Networking.Instantiate is only needed for objects that derive from SimpleNetworkedMonoBehavior / NetworkedMonoBehavior. If you are spawning a regular gameObject/MonoBehaviour then there is no need to use Networking.Instantiate.

    Here is sample code of how you would instantiate a normal game object (say like particles or effects):
    Code (CSharp):
    1. using UnityEngine;
    2. using BeardedManStudios.Network;
    3.  
    4. public class SpawnOffNetwork : SimpleNetworkedMonoBehavior
    5. {
    6.     // Assign this in the inspector
    7.     public GameObject spawnThis = null;
    8.  
    9.     // Call an RPC method to spawn the offline object
    10.     [BRPC]
    11.     private void Spawn()
    12.     {
    13.         GameObject.Instantiate(spawnThis);
    14.     }
    15.  
    16.     private void Update()
    17.     {
    18.         if (Input.GetKeyDown(KeyCode.Space))
    19.             RPC("Spawn");
    20.     }
    21. }
     
    Neo-Gamefactory likes this.
  49. dudedude123

    dudedude123

    Joined:
    Aug 24, 2013
    Posts:
    120
    Do you have to use network view for it?
     
  50. farrisarts

    farrisarts

    Joined:
    Jul 13, 2012
    Posts:
    881
    Nope :). If your object derives from a NetworkedMonoBehavoir or SimpleNetworkedMonoBehavior. It is treated as a networked object :).

    Here is our tutorial on how it works step by step in it's simplest form :)
    http://beardedmanstudios.com/getting-started/step-by-step-example/