Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - cmifwdll

Pages: 1 ... 17 18 [19]
TNet 3 Support / Re: Channel and host data
« on: November 07, 2015, 07:50:43 AM »
Hello everyone,

I have a doubt regarding channel and server creation.
Right now, what I am doing:
- I have a main server hosted in Amazon
- All players will connect there to handle channel creation, hosting and playing (I think it is the same way as the Aren game works)
- How can I setup the name of the channel (in channel parameters, there is only level name, no channel name... is custom data the only way?)
- How can I ping each channel when getting channel list? Right now I can only ping the server I am in... is this the only way? With this, I suppose, all players will have the same ping because they are all in the same main server?

I think I misunderstood the way channels in TNet works.
I still have my old way, which is all players creates their own server instance, so I save their server data in a private database (mySQL) and get info from there to generate my own channel list. I thought having some kind of master server and using hosting channels to provide players host and client will be easier to keep everyone playing without port forwarding.

If anyone can help me, I appreciate it.
Thanks in advance.

I explained in your other thread that players deemed a channels "host" aren't really hosting anything. The channel exists on the server. The server "hosts" the "channel", the player *operates* the channel. To reiterate: the channel is part of the server. A server can have many channels. A channel exists solely and entirely on the game server. To "join" a channel simply tells the server you're part of a specific group of clients.

You can set the name in the channel data, yes. You can then retrieve the name from the channel data.

Like I said, the channel is just a collection of data on the server. Therefore, the server ping is your ping to each and every channel on the server.

All players will *NOT* have the same ping. I think you misunderstand how networking works. I really don't know where to begin explaining that... so, let's say every networked device is connected via Ethernet (that blue cable thing - I'm sure you've seen it). If this is the case, you can picture the Internet as a huuuuuge collection of devices all connected by blue cable. One giant blue cable with devices breaking it up. So, networking, then, is determining which path to take to reach a destination. You would have to determine which device nearest to you to talk to, and that device determines the next device, and so on and so on until you reach your destination. So how many devices are between you and your destination, the distance between each device, and how fast each device determines the next device greatly effects your ping. I recommend playing around with the "tracert" program in Windows (or "traceroute" in linux / mac). Type "tracert" in command prompt (or "traceroute" in linux / mac terminal). Each "hop" is a device on the way to reaching google, so you can see the exact path your network resolved.

Mine is different.

I have a list of different servers that hook up to the lobby server. Then a simple list showing all the different servers (not rooms). How do I go about pinging each server when not connected to it. In the list I have server name and numbers of players showing, there's no option for ping (only when connected, as done by the example menu).


Try TNManager.Ping(IPEndPoint udpEndPoint, GameClient.OnPing callback). You can get the EndPoint from TNLobbyClient.knownServers.list[_index_].externalAddress (or internalAddress).
If it doesn't work then at least you have a starting point :)

TNet 3 Support / Re: Hosting bandwidth and server
« on: October 27, 2015, 08:42:20 PM »
related question:

does a RFC communicate client to client?  ive always assumed RFC is still relayed by a server.

You call RFCs via tno.Send / tno.SendQuickly. Yes, RFCs pass through the server. There's no client to client communication in TNet except for LAN broadcasting.
In case you meant RCCs, yes, those are relayed too. They're basically RFCs with an additional designation.

well, ok, thanks, I will check this out as soon as I start to test more.

If you've coded your game so that your Target parameter in most of your tno.Send / tno.SendQuickly calls is Target.Host, and very rarely target Target.All then of course Player A (the operator) is going to receive more data than Player's B and C, but even then the server will be consuming the *most* because all tno.Send / tno.SendQuickly calls pass through the server regardless of the Target parameter.

In reality there probably won't be much of a difference in how much data Player's A, B, and C send / receive, because you're likely going to be using Target.All / Target.Others just as much as you use Target.Host. This doesn't mean you can get away with generating 10 MB/s of net data though :P be wary of what you're syncing and how often. Aren has offered much advice on this subject. Particularly movement and anim syncs (don't sync the anim state, sync the input and have each client run the anim themselves).

TNet 3 Support / Re: Hosting bandwidth and server
« on: October 25, 2015, 07:40:12 PM »
Again, think of the server as a relay. However you decide to code your game will determine whether player A consumes more bandwidth than player B. Regardless, though, the server will always consume the most because all data passes through it.

TNet 3 Support / Re: Hosting bandwidth and server
« on: October 25, 2015, 01:23:27 PM »
Packets are sent to the server, and the server then relays them to others.

In my opinion I think the term "host" should be refactored to "operator" to avoid confusion.
  1. Player A calls tno.SendQuickly(rfcID, Target.Others, someData):
  2. * Packet is sent to server
  3. * Server determines who to forward the packet to based on Target parameter
  4. * Server forwards the packet to targets
  6. Player A calls tno.SendQuickly(rfcID, Target.Host, someData):
  7. * The RFC is executed locally, no packets sent
  9. Player A calls tno.SendQuickly(rfcID, Target.All, someData):
  10. * The RFC is executed locally
  11. * Packet is sent to server
  12. * Server determines who to forward the packet to based on Target parameter
  13. * Server forwards the packet to targets
  15. Player B calls tno.SendQuickly(rfcID, Target.Others, someData):
  16. * Packet is sent to server
  17. * Server determines who to forward the packet to based on Target parameter
  18. * Server forwards the packet to targets
  20. Player B calls tno.SendQuickly(rfcID, Target.Host, someData):
  21. * Packet is sent to server
  22. * Server determines who to forward the packet to based on Target parameter (Player A in this case)
  23. * Server forwards the packet to Player A
  25. Player B calls tno.SendQuickly(rfcID, Target.All, someData):
  26. * The RFC is executed locally
  27. * Packet is sent to server
  28. * Server determines who to forward the packet to based on Target parameter
  29. * Server forwards the packet to targets

So, you can really think of the server as a souped-up relay, and the "host" (operator) as a client with a special authoritative designation.

TNet 3 Support / Re: Steam API / Steamworks
« on: September 23, 2015, 12:59:08 AM »
Hello @ArenMook
Thanks for your reply.

Yes, it is about integrating it. We know it is separate from TNet. I am just asking if someone already did something (as it seems you did) to point us in a right direction.
What we want to do is:
- Cloud saving
- Achievements
- We will have some kind of master server. And we want to show the room list in some kind of a lobby. But we want to integrate Steamworks to show this list and make friends to connect through Steam, as many other shooter games does.
Is there any way that you can help us? Sorry to be direct here, but are you available for a quick consulting (paid)?

Thank you all for your help.

I don't have any experience with adding Steam functionality to a game (yet), but a few minutes of browsing the Steamworks.NET website lead me to this test project:

So, within that project, you can find examples for the things you're asking for:
1. Cloud saving = SteamRemoteStorageTest.cs
2. Achievements = SteamUserStatsTest.cs
3. I'm not sure what you're trying to accomplish with this one. I think you'll need to build the serverlist yourself using TNet (there is code posted in the FAQ). However, for things like displaying the servers your Steam friends are playing on and joining their game via the Steam client I think you'll need bits and pieces from SteamFriendsTest.cs, SteamMatchmakingServersTest.cs, and SteamMatchmakingTest.cs. I'm not entirely sure about the last two, but it's worth fiddling around with.

Joining a game via the Steam client either starts the game with a launch parameter (I think?), or, if the game is already running, the GameRichPresenceJoinRequested_t callback is fired.

Again, no experience with integrating Steamworks in a Unity game, but this is more than enough information to get you - or whoever you hire - started.
Hopefully in providing this starting point you can better estimate the value of the work you're asking for (hint: it's probably not a lot).
Just don't want you to overpay :)

TNet 3 Support / Re: Steam API / Steamworks
« on: September 18, 2015, 03:03:59 PM »
It kind of seems like you're asking for handouts...

If you truly need a nudge in the right direction: most Unity developers use Steamworks.NET, a wrapper created by Riley Labrecque, and it can be found here:

I think you can download it from the Unity asset store as well. Not sure.

From there, research the wrappers documentation and the documentation that Valve supplies and you should be able to get up and running.

Steamworks API documentation:
Wrapper documentation:

TNet 3 Support / Re: Losing Packets
« on: September 14, 2015, 06:39:40 PM »
Hi, it appears that I'm somehow losing packets. (For example: I switch from day to night and one of the connected machines stays in day mode)
Now I thought that this can't happen with TCP, isn't TCP guaranteeing that every packet arrives?  (unless of course there's no connection)

How is TNet handling this? What happens when a packet can't be delivered? Will it re-try? When will a client disconnect?

Can you fire up wireshark on both the sending and receiving machine to verify the packet is indeed being dropped?

What I think is most likely happening is that the packet is arriving, but your RFC doesn't do what you intend it to do. You could place a breakpoint or a Debug.Log at the very top of your RFC to verify that it's being called. If it's being called then the packet has arrived and has been processed.

As for your follow-up questions, I'd have to dig into TNet to answer [which you can do as well, mind you :)]. Perhaps someone else will be able to answer those questions.

TNet 3 Support / Re: <TNObject>().isMine Issues
« on: July 31, 2015, 01:15:50 PM »
Very strange. Can you place a Debug.Log to verify the right block is being executed?
One possible thing I can think of: GetComponent<TNObject>().isMine is evaluating properly, but your enable / disable code doesn't do what you intended.
Another thing: Are you instantiating the object with TNManager.Create?

Also, if you use GetComponent<TNObject>() a lot in a script, you should derive from TNBehaviour. This allows you to use its member "tno". Saves you some calls to GetComponent ;)

TNet 3 Support / Re: TNet is very troubling (furious)
« on: July 29, 2015, 08:35:48 PM »
Hello, I read your post so I can try to help, and I did. My issue with your post is that it lacks information making it difficult to pinpoint the exact issue. I have kept searching through TNet's code and found a possible solution to your problem. I believe I understand why you can't connect to your server (oh so many reasons). I wasted about 10 full minutes of my time to search for a possible solution for you. You tell me very good things about yourself, but I really am not seeing it. I have been coding networking (and englishing) for about 2 years and I'm really happy with TNet as a networking solution because it allows me to modify it to suit my needs.

Here's what I *think* you need to do (I'll make it easy to copy-paste):
Change this:
  1. public void HostServerTest (GameObject Button)
  2.     {
  3.         mUPnP = new UPnP();
  4.         /*mUPnP.Start();
  5.         mUPnP.WaitForThreads();*/
  6.         mUPnP.OpenUDP(5127, OnPortOpened);
  7.         TNServerInstance.Start(5127, 0, "server.dat");
  8.         TNManager.Connect("");
  9.     }

To this:
  1. public void HostServerTest ()
  2.     {
  3.         TNServerInstance.Start(5127, 0, "server.dat");
  4.     }

/end snarky reply

Seriously though, I'm assuming two things: 1. You are uncommenting the line TNManager.Connect in your second code snippet when you test. 2. You are launching the server and trying to connect using the button from your second code snippet in the same game instance. If this is the case, then the changes I posted could fix the error for you. If it's not the case, you're going to have to provide more information for me to help further. Where is the error coming from? Is it the TNServerInstance or the GameClient?

If it is the case and the changes I suggested do work, let me explain: You're calling TNManager.Connect in the same function you create the server, then you call TNManager.Connect a second time when you click the button (assuming you uncomment that line in your test). The TNManager.Connect function first calls Disconnect which shuts down and closes the Socket, then it goes through the connection process, opening a new Socket and connecting. This shouldn't be an issue normally, but it's possible, and it's the first thing I can think of. So, in short, there's really only need to call Connect once.

Additionally, since you aren't specifying the optional openPort parameter in your TNServerInstance.Start call, it's automatically doing the upnp stuff for you, so you can safely remove that. Unless you want additional control over the upnp stuff, in which case you need to set the optional openPort parameter to false. TNet gives you that control and that choice because it's a great networking solution.

Just tried reproducing, I was able to start and connect (twice) with the following:
  1. public void OnClick(string sender)
  2.         {
  3.                 if (sender == "btnStartServer")
  4.                 {
  5.                         TNServerInstance.Start (28001, 0, "server.dat");
  6.                         TNManager.Connect("");
  7.                 }
  8.                 else if (sender == "btnJoinServer")
  9.                 {
  10.                         TNManager.Connect(serverAddress, serverPort);
  11.                 }
  12.         }
Steps: click Start Server button, wait, click Join Server button.
Result: It connects twice with no errors.
Additional Info: serverAddress variable is and serverPort variable is 28001. Scene contains a GameObject with the TNManager component attached.

However, I noticed in your snippet your first call to Connect is using a public IP allocated to a residential ISP (comcast). Is this your WAN IP? It's very rare for routers to support hairpinning. Try switching both calls to Connect to use either loopback address ( or your LAN address (eg; 192.168.1.x - you can find your LAN address many ways, ipconfig in cmd prompt, network and sharing center in win7, reading the debug log from TNManager.Awake, google). Even if it's not a router issue, it wouldn't hurt to make sure the call to Connect is using the proper IP (loopback or LAN if hosted on same machine or network, WAN if the server is hosted outside your network).

TNet 3 Support / Re: TNet is very troubling (furious)
« on: July 29, 2015, 04:22:24 PM »
Tnet comes with full source code. No information is being kept from you. While it's not always feasible to go through the full source code due to time constraints, a brief glance is more than enough to get a sense of how it works. Moreso, if you're encountering an error message you can search through the code and find exactly where the error is thrown, and then trace it back up to see where the problem (and solution) is.

The error message you posted is a socket exception. I'm not sure which C# Type, but I am sure MSDN knows. A big part of programming is encountering errors, tracing that error, researching why that error occurs, and finally fixing that error.

I've been watching your recent threads and it seems to me that you're just copy-pasting without really understanding what you're doing. Regardless of how great tnet support is, I don't think anyone will hold your hand and write all your networking code for you.

I think exactly 100% of the questions you've asked can be answered by going through the supplied demo scenes and viewing the associated code.

Furthermore, thorough documentation does exist:

PS: typed on a phone, I apologize for typos or poor formatting.


TNet 3 Support / Re: Pre-Sale Questions
« on: July 24, 2015, 12:25:55 PM »
Wow... It's always the simple things overlooked. Thank you.

TNet 3 Support / Re: Pre-Sale Questions
« on: July 24, 2015, 10:15:01 AM »
No, because the server doesn't know anything about components or Unity at all, so it can't count how many TNObjects are needed. Plus it doesn't matter if you only have one TNObject per instantiated game object. The same way you can have multiple people living at the same address, you can have your scripts with RFCs be attached to child objects and they will still be found automatically. You may need to change TNBehaviour to this though, depending on your version:
  1. public abstract class TNBehaviour : MonoBehaviour
  2. {
  3.         [System.NonSerialized] TNObject mTNO;
  5.         public TNObject tno
  6.         {
  7.                 get
  8.                 {
  9.                         if (mTNO == null) mTNO = GetComponentInParent<TNObject>();
  10.                         return mTNO;
  11.                 }
  12.         }
  14.         protected virtual void OnEnable ()
  15.         {
  16.                 if (tno == null)
  17.                         mTNO = gameObject.AddComponent<TNObject>();
  19.                 if (Application.isPlaying)
  20.                         tno.rebuildMethodList = true;
  21.         }
  23.         /// <summary>
  24.         /// Destroy this game object.
  25.         /// </summary>
  27.         public virtual void DestroySelf () { if (mTNO != null) mTNO.DestroySelf(); }
  28. }

Thanks to this post we went ahead and purchased TNet. I've been porting the project over, and I'm really, really satisfied with TNet. The flexibility is insane. The custom object creation is insane. The serialization is insane. My Item class implements your IBinarySerializable interface and I can spawn a new Item with just ~45 bytes over the network. I highly recommend TNet to any prospective buyer.

However, I'm having a weird problem. When I attach an Item component (derives from TNBehaviour) to a child gameobject of my Player, a new TNObject is automatically added to that child gameobject.

The automatically added TNObject has the same ID (seen in the scene view) as the TNObject on the root Player gameobject, but there's some differences.
When debugging and viewing the properties of both TNObjects, the following are different:
id - matches the uid on the root Player gameobject, 0 on the child gameobject
mIsRegistered - true on the root Player gameobject, false on the child gameobject
mParent - null on the root Player gameobject, the Player gameobject on the child gameobject (as it should be)
mRFCs - 4 on the root Player gameobject (3 in the Player class, 1 in the AutoSync class), 0 (buffer is null) on the child gameobject (there are *2* RFCs in the Item class!)
rebuildMethodList - false on the root Player gameobject, true on the child gameobject

It's very odd that a new TNObject is even created. I looked for all calls to AddComponent<TNObject>, and the only place it can be added is TNBehaviour. So I set a breakpoint and it's not hit when adding the Item component. I think the TNObject is being added non-generically somewhere (AddComponent(Type) instead of AddComponent<TNObject>()), and the properties are being copied from the parent TNObject via reflection, but something is going wrong with the copy / update process.

This is all with the changes to TNBehaviour you posted.

I can workaround this by adding
  1. tno.rebuildMethodList = true;
  2. if (tno.parent != null)
  3.     tno.parent.rebuildMethodList = true;
to the Start() function of my Item class, but this feels like a band-aid solution.

TNet 3 Support / Re: Pre-Sale Questions
« on: July 16, 2015, 05:56:49 PM »
This seems very limiting, and unfortunately won't work with my project. Because of the invasion-mechanic, players must be instantiated. Do you have any plans to change the way you assign IDs? Maybe you can traverse the gameobject when it's instantiated and assign IDs to each child traversed (that has a TNObject)?

It seems really wrong to me that every multiplayer game puts all their networking logic in a single class. Am I looking at it the wrong way? Should I just bite the bullet and clutter up my Player class?

TNet 3 Support / Re: Pre-Sale Questions
« on: July 15, 2015, 02:21:34 AM »
Thanks for getting back to me so quickly.

I think I have a better understanding of your concept of channels now, and I think they'll make NAT a non-issue.

6. To send messages such as "attack", use RFCs: tno.Send("SomeFunction", TNet.Target.All, ...); Do not call these functions directly. That's the main difference between making a single player game and a multi-player game. Instead of calling functions, you will be sending messages to call those functions. And that's it.

My question wasn't how to invoke functions on other clients, rather, the restrictions on where we can send, receive, and process these messages. Will I be able to send (and receive) a RFC on a component attached to a gameobject that is a child of the root player gameobject?

For example, in the following scene hierarchy:

There is a Player gameobject with several child gameobjects. Each child gameobject would have a script attached to it, like so:

Would this script be able to send, receive, and process RFCs given its position in the object hierarchy? If yes: would this object require its own NetworkIdentity component (I think you call it TNObject)? If yes to that question: would having a TNObject on each child gameobject, along with one on the root player gameobject, cause problems? To elaborate on a (the) possible problem: using Unity's networking, each gameobject that makes use of networking must inherit from the NetworkBehaviour class (and have a NetworkIdentity component attached), and from there you use isLocalPlayer to determine if you own the gameobject. The problem is that isLocalPlayer only evaluates to true on the root player gameobject, NOT on its children.

edit: forgot to explain the importance of isLocalPlayer. isLocalPlayer, a property of the NetworkBehaviour class that all networked entities inherit, is used a lot in Unity's internal network functions. Most importantly, when calling any function with the [Command] attribute (similar to tnet's RFC system, but strictly client -> server), the *internal* Unity function (meaning something I have no control over), SendCommandInternal is called, and the very first line of this function checks to see if isLocalPlayer is true or not. If it's false (and it is on child gameobjects), the function returns and the [Command] is never sent over the network. So that's why I need to know if tnet handles child gameobjects differently, and if I'll be able to send and receive RFCs on these child gameobjects.

I hope I explained my question(s?) adequately. I really suck at articulation.

TNet 3 Support / Pre-Sale Questions
« on: July 13, 2015, 10:06:31 PM »
I've been fighting (big emphasis on "fighting") Unity's networking for a few weeks now, so I'm at the point where I need to start looking for other solutions. I'll try to convey what I need for my project, and hopefully with feedback I'll be able to determine if TNet is the right fit.

Some things which I feel may be relevant:
* The project is using the latest version of Unity (5.1.1p4)
* Standalone Desktop platform only
* Host-based multiplayer (one player acts as both client and server)
* The Host is the authority (performs all physics, attacks, damage, movement, etc. Clients are not trusted)
* Invasion mechanic (dark souls style) (will explain more below)
* I come from a programming and networking background, but not a game development background

Upon startup, players register with the master server and begin sending heartbeats at regular intervals. When invading, players tell the master server "hey, here's my latest info, find me a match". The master server does some processing to find a match, and tells both players when a match is found. In doing so, the master server acts as a NAT punchthrough facilitator, in addition to its role as a master server. I've got the master server set up, put it up on a VPS and tested using two separate WANs, and all is well. The problem comes with implementing this into Unity. Without going too much into it, the problem is that I can't make use of Unity's underlying Socket. I need to be able to send/receive packets to/from any destination from the same Socket the game is being hosted on. Or, at the very least, be able to handle NAT punchthrough and matchmaking from within the engine.

Additionally, Unity has some weird... technical limitations. Logical structure is very important for this project. It needs to make enough sense that junior coders will be able to add on to it. Following this paradigm, the Player class handles the Player stuff, the Inventory class handles the Inventory stuff, the Weapon classes handle the Weapon stuff. Of course, the Player class has an Inventory instance, and the Inventory instance holds an array of Weapon instances, but it all meshes well and each part handles its own stuff, as you'd expect. I really feel like this part is important to convey, so I'll give an example: The Player class handles Input, and when the Input for "attack" is detected, the Player class calls playerInventory.EquippedItems[SlotType.MainHand].Attack(). This will call the Attack function on the equipped Weapon. The Weapon class then handles animating the weapon swing, in addition to performing the hit detection and damage calculation server-side. Unity doesn't allow for this behaviour because my Weapon component exists on a child GameObject of the root Player GameObject. Calling a Command in the Weapon class from the Weapon class will result in a "Trying to send command for non-local player" error, because, according to Unity, a child GameObject of a parent GameObject that IS the local authority isn't the local authority. The parent is the local authority but the child isn't. I need to be able to declare and call networked functions from each Component, regardless of its position in the GameObject (Scene?) hierarchy. Unity's solution to this is to put all the logic in one place, the Player class, and have the Weapon class call that. This becomes really messy when there are multiple Weapon types, each with their own attack logic, all inheriting from a base Item class.

To summarize my needs:
* I need to be able to handle NAT punchthrough and communication with my own matchmaking server while *simultaneously hosting* a game
   * Or, if that's not possible, I need to be able to send/receive packets to/from any destination from the same Socket the game is being hosted on
* I need to be able to declare and call networked functions from any Component, regardless of its position in the hierarchy.
   * For example, a Weapon component is on a child GameObject of the GameObject that has local authority (the Player GameObject). That Weapon component needs to be able to declare and call [Command] and [ClientRpc] functions to perform hit detection and damage calculations on the server.
Going through the forums I see a few posts with the same issues, and the replies typically point out a design flaw. Since I lack game development experience, is there a flaw with my design? Should I be thinking about this differently?

Pages: 1 ... 17 18 [19]