Author Topic: TNet: Network Level Loading  (Read 10501 times)

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
TNet: Network Level Loading
« on: September 21, 2014, 07:24:25 PM »
Hi,

I'm one of the two guys working at [in]Sanity Interactive, a co-op game development crew that is currently working on a shooter project, which will feature both dedicated server and private matches where the player hosting the match is able to play as well. We have been using Unity's built-in framework (RakNet) and we've had troubles trying to get the network layer to work correctly when sending RPCs back to clients so they can load the right level.

I was wondering if you could confirm if TNet has server-instructed level loading capabilities, and if you could post a snippet of code that would be the basis of the server telling the client what to load.

When the player connects to the server hosting the game, before the client should do anything, the server sends a message (let's for arguments sake say "clientLoadLevel") to the client, with a string of it's level that is currently loaded (called from Application.levelLoadedName, etc). The client must then accept this message and start loading the level (I see TNet has TNet.LoadLevel which is nice!) otherwise I intend to kick the client saying "Wrong level loaded" to prevent really weird stuff happening.

So, in pseudo code:

Server: Client connects > Client, clientLoadLevel("mp_testlevel") > *waits for client response * > Okay, you've loaded, welcome to the game
Client: Connect to server from mainmenu > Server, what is the level? > Okay, I'll load mp_testlevel > Yay!

The thing here, is that in our current Unity RPC implementation, is that the RPC gets fired in a different scene since the server has loaded the level (let's say mp_testlevel) and since the client is on the main menu, it freaks out and errors or doesn't load the level and weird stuff starts happening.

So, this is one of the things I'm looking at in TNet. Plus, for shooters, I need a robust and reliable solution because I don't want major network glitches due to bugs in Unity's set-up. I realize that TNet is only the networking cake, and my game is the icing on top of that, but if you can confirm I can do the level loading as shown above, then you pretty much have a purchase.

Cheers!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #1 on: September 22, 2014, 10:52:31 AM »
By default TNet's server is just an echo server, for the most part. You send messages to it with certain flags, and it will decide what to do with them. It may forward them to all players, to one player, or do something with the message and send out a different response.

The first player to join a channel is that channel's "host" (think channel operator in IRC terms), and you can check this value on the client side (TNManager.isHosting) to determine if certain logic should be executed or not (AI scripts for example).

The server doesn't run any game-specific logic by default, and it's not advisable to do so. You should be doing this on clients. In your example, this is how I'd do it:

1. Client 1 connects, and with TNet you specify which scene to load on a successful connection (for example scene "First").
2. Client 1 receives a "joining channel" notification, along with the scene to load ("First"), and loads the scene (done automatically).
3. Client 1 gets OnNetworkJoinChannel(true, null) -- the channel has been joined successfully and the scene was loaded.

Note how everything is done on the client, it merely goes through the server? The server validates everything and sends the corrected messages. Examine the next client:

1. Client 2 connects and chooses level "Abc123" as the desired scene for TNManager.JoinChannel.
2. Client 2 receives a "joining channel" notification, along with the scene to load ("First", not "Abc123", because the first player created the channel, not this one!), loads the scene.
3. Client 2 gets OnNetworkJoinChannel(true, null).

So although the second client requested a different scene, the first player's choice is what gets sent back to him.

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #2 on: September 22, 2014, 05:23:05 PM »
Thanks for the quick response. This clears the confusion a fair bit. ;)
If I am not mistaken, does TNet automatically reply to client 2's joining notification with the level ID when client 1 is hosting? Or would I have to fire a RFC or custom packet to client 2?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #3 on: September 23, 2014, 12:52:22 PM »
Level names, not IDs -- but yes. For other notifications, it depends on the notification. TNet will always send all created objects and RFCs you marked as "saved" before the join operation completes (Target.AllSaved, Target.OthersSaved). TNet won't send any RFCs you marked as not saved (Target.All, Target.Host, Target.Others).

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #4 on: September 23, 2014, 08:19:18 PM »
Thank you for confirming. Well, you have a purchase!

So, when clients connect to the server, will they automatically be created on the client-side? I remember there was a "Auto Create" script going back a few builds that would auto create objects in the scene when it loaded?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #5 on: September 24, 2014, 02:50:56 PM »
What I do in Windward is in my game scene there is a game object with TNAutoCreate on it that will create an instance of the player. So as soon as the player joins, he will create an instance of his own avatar, basically.

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #6 on: September 30, 2014, 01:07:25 AM »
How would one go about putting a splash screen with a preview of the level before TNet actually joins the channel and loads the specified level?
At the moment, I have "server and client" functionality working - you select your server parameters, and then hit start and TNet boots up.

This is no biggie for the host. I can just make a toggle that will overlay the "Loading..." screen with a level image and then use TNet.LoadLevel("blah");

However, on the client, we connect to the server, then join channel 1 (which is the actual game channel). However, unless we poll the ChannelList first so we can get the level parameter from the channel that the game is happening on, the client will just "freeze" on whatever was there in the scene until the level is done loading.

Is it possible to get a channel's data like TNManager.client.RequestChannelInfo(id of channel) ? This would be really beneficial, because I can fetch the level out of the returned info, display the respective splash screen and then let TNet do the loading.

Or do you have another idea?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #7 on: September 30, 2014, 04:33:13 AM »
Join a dummy channel first, then Application.LoadLevelAdditive the actual level.

In Windward I don't even generate the actual level beforehand. Levels are procedural, so all I have in my scene is the UI, open to the loading screen by default. So the first thing users see when they join that channel is the loading screen, which then proceeds to do procedural generation in the background over the course of multiple frames.

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #8 on: October 01, 2014, 02:55:54 AM »
So, you're saying create the server, then join a channel with the respective ID (let's say 1) and the levelname of say "mp_superflat_loader" that contains the UI overlay of the loading screen and the level loading script. TNet will load that level, which will start the actual proper level loading process, which level is "mp_superflat_real".

When the level loading isDone flag is true, then the script triggers the "OnLevelWasLoaded" call to spawn the client-side player manager, destroys itself, and then the player has it's control ?
Would I need to tell TNet to pause network queue processing before I start loading? Or will TNet detect I'm loading the level and auto-pause itself?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #9 on: October 01, 2014, 05:38:56 PM »
TNet doesn't track level loads you do yourself.

1. When you want to join a channel, first Application.LoadLevel your scene with the loading screen. Set this screen's game object to be DontDestroyOnLoad, and proceed to TNManager.JoinChannel to your proper game scene.

2. When you get OnNetworkJoinChannel, fade out your loading screen, then destroy the game object you marked as DontDestroyOnLoad.

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #10 on: October 02, 2014, 02:05:26 AM »
Uh.... double quote, wth?  :o

TNet doesn't track level loads you do yourself.

1. When you want to join a channel, first Application.LoadLevel your scene with the loading screen. Set this screen's game object to be DontDestroyOnLoad, and proceed to TNManager.JoinChannel to your proper game scene.

2. When you get OnNetworkJoinChannel, fade out your loading screen, then destroy the game object you marked as DontDestroyOnLoad.
Alright, I took your advice and it worked as intended.

When I connect to the server (in this case, a in-game hosted one), I immediately load a dummy scene (mp_superflat_load) with the splash image and invoke joining the channel that loads the correct level (mp_superflat). There is a little delay as Unity loads the level. When the channel is joined, it sets a flag, eases out the splash image which reveals the level and everything under that. Let's just hope it doesn't bug out. :P

Now with this in mind, I can focus on player controls and Network Sync...
« Last Edit: October 02, 2014, 02:30:52 AM by MCoburn »

ndizazzo

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 3
    • View Profile
Re: TNet: Network Level Loading
« Reply #11 on: October 02, 2014, 07:46:12 PM »
The server doesn't run any game-specific logic by default, and it's not advisable to do so. You should be doing this on clients.

Do you mean this in general, or for this specific scenario? I hate to hijack the thread but I was curious as to why you recommend not doing logic on the server with TNet.

I was under the impression I could build an authoritative server with TNet that ran a game simulation and updated each client. The clients could worry about prediction, rendering, gathering input to change the simulation.

MCoburn

  • Jr. Member
  • **
  • Thank You
  • -Given: 1
  • -Receive: 7
  • Posts: 69
    • View Profile
Re: TNet: Network Level Loading
« Reply #12 on: October 02, 2014, 10:56:07 PM »
Do you mean this in general, or for this specific scenario? I hate to hijack the thread
No offense taken. You raised a valid point.

but I was curious as to why you recommend not doing logic on the server with TNet.

I was under the impression I could build an authoritative server with TNet that ran a game simulation and updated each client. The clients could worry about prediction, rendering, gathering input to change the simulation.

My setup that I'm hoping to implement is sorta semi-authoritative. The server will run the prediction when you shoot your weapon, and report back to the client that request the shot "that's a hit on X", "that's a hit on Y", "no, you missed Z".

The problem with authoritative, is while the server is the master and controls everything, that's a lot of work for the server to do. If you have the CPU, RAM and knowledge then sure, you can do it - TNet is just a cake and you can put whatever icing you want on top. In my setup, I prefer to have the clients be "dumb" to some extent, but when you fire the weapon, the hosting player has the final say.

The host handles the Score Board and weapons. The connecting clients just report to each other where everyone is and what they are doing (moving, dead, idle ... etc). One thing we also need to do is Entity Rewinding... to help compensate for lag/jitter.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNet: Network Level Loading
« Reply #13 on: October 02, 2014, 11:24:10 PM »
@nzizazzo: It's better for you as a developer. 1000 clients means 1000 work-horses for you to utilize, instead of having your poor server do 1000 times more work. The more you offload onto your clients, the better off for you, and the more clients you will be able to support.

P.S. Where are you working at nowadays, Nick?

ndizazzo

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 3
    • View Profile
Re: TNet: Network Level Loading
« Reply #14 on: October 04, 2014, 01:01:11 PM »
My setup that I'm hoping to implement is sorta semi-authoritative. The server will run the prediction when you shoot your weapon, and report back to the client that request the shot "that's a hit on X", "that's a hit on Y", "no, you missed Z".

The problem with authoritative, is while the server is the master and controls everything, that's a lot of work for the server to do. If you have the CPU, RAM and knowledge then sure, you can do it - TNet is just a cake and you can put whatever icing you want on top. In my setup, I prefer to have the clients be "dumb" to some extent, but when you fire the weapon, the hosting player has the final say.

The host handles the Score Board and weapons. The connecting clients just report to each other where everyone is and what they are doing (moving, dead, idle ... etc). One thing we also need to do is Entity Rewinding... to help compensate for lag/jitter.

What level of cheat-prevention are you aiming for in your project? Because with the strategy you outlined, I'd imagine it'd be fairly easy for clients to misreport their location to peers, and cause some major issues. Doing hit / collision checking on one host should avoid major score / state synchronization issues, but wouldn't a client misreporting it's position cause problems? Client A could report it's position falsely and make it to be nearly impossible for clients B, C, and D to hit client A between the update on their screens and the roundtrip back to the "host".

I ask because I feel like your end-goal is the same as my own, and am at the point where I have to make smart architecture decisions. It's pretty desirable to have the server doing as little as possible, but having no cheating is important too.

@nzizazzo: It's better for you as a developer. 1000 clients means 1000 work-horses for you to utilize, instead of having your poor server do 1000 times more work. The more you offload onto your clients, the better off for you, and the more clients you will be able to support.

Agreed, having the server do as little as it can is the best since you don't have to have a powerful server behind it, but how would one strike a good balance between keeping the game cheat-free, and having work offloaded to each client?

I see two extremes: one end of the spectrum is having clients do everything, but that is the worst-case scenario for cheat prevention and best for resource utilization. The opposite is having a server do everything, which is the best case scenario for cheat prevention, but terrible on resource utilization. I realize it's really dependent on the game, but is semi-authoritative generally the balanced option?

Have you ever written anything about your networking strategy for Windward? I wouldn't mind reading through something like that :). It might even be a good piece to convince more people to use TNet.

P.S. Where are you working at nowadays, Nick?

I'm taking a break from games to make some money, haha... I'm with The Toronto Star / Metroland right now doing mobile development. I'm working on some game side projects though, to stay sane (in fact, I just picked up TNet for the project!).

You working at Unity still?
« Last Edit: October 04, 2014, 04:05:00 PM by ndizazzo »