Author Topic: Best way to design my network functionality  (Read 4594 times)

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Best way to design my network functionality
« on: August 24, 2014, 12:38:24 PM »
Hey guys,

I am currently playing around with TNET and have a hard time to grasp its concept. I am totally new to game development, so I have no experience in programming networked game-applications. I am a (kind of  ;D) professional .net-dev though.

I grinded through the tutorials and managed to implement very basic networking in my space game. Now, I stumbled across some design questions I wasnt able to answer myself.

Basically you can imagine my multiplayer game very much like the minecraft multiplayer: The (hosting) player owns the savegame, containing a procedurally generated and player-altered universe containig many star systems. A star system would be sth like a minecraft map: it contains stuff that players manupulate in some kind and those changes needs to be saved into the savegame of the host.

Now a second player connects and jumps into another star system. This transition will be done via channel-change, so each star system actually played into will have a channel. The loaded level will be the same though, the GameObjects will be createy by script depending on the players system. Thats where my problems are starting. Now the second player should be the "host" or "master" or whatever of the new channel, right? So, now he flies around, destroys some asteroids and a space station. Then he logs out. Now, those changes he made to the star system must be saved into the hosts savegame...

First of all - is it possible to achieve this concept using the standard 24kB server that is contained in the package? I really like the concept of this thing... if yes - well... how and where to start? ;) Or do I need to implement a "standalone" server?!?
May I create the (static) planets without user-interaction as simple Instances without using the TNManager.create method (for all players, or just the host?)?
Where can I attach the save-logic, and how do I find out if the actual player really needs to save the stuff - it woud be the player that created the first channel...

I hope you can enlighten me a bit... I really will need some time to get into this networking...
Thanks!
Malte

« Last Edit: August 24, 2014, 12:51:33 PM by DocEvil »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #1 on: August 24, 2014, 08:00:42 PM »
Yes, it's possible, and is indeed how TNet was designed. When creating a channel, you have an option to make all the changes to it persistent. By default it's off. Pass the correct boolean parameter to turn it on.

When creating game objects via TNManager.Create or TNManager.CreateEx, you also have a similar option. Should the object be destroyed when the player that created it leaves? For a spaceship controlled by the player you will want it to be so, but for things like asteroids that you create dynamically, you will likely want to keep them even if the player that created them (the host) leaves the star system/channel.

That boolean flag is all it takes to make things be saved.

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #2 on: August 25, 2014, 07:48:21 AM »
Mhmm, so my 2nd player joins channel "4" and his client now "hosts" the "level". How does his client know, if it needs to create these asteroids because the system was never visited before - or, in the opposite, to simply join the channel and get the already existing gameobjects from the server(?)?

Edit 1: Okay, I am getting some wierd results now. Playing with one client, the following happens:
- Client connects, everything as intended, roid is there.
- I shoot the roid and then open the map (chance of channel)
- then I return to the space channel and the roid is once again being created.

Same effect for two players, everytime a player joins the channel, a roid is spawned. I understand that !TNManager.isThisMyObject isnt enough to ensure a one-time exceution of this code:
  1. if (!TNManager.isThisMyObject) {
  2.                         return;
  3.                 }
  4.                 GameObject obj = (GameObject)Resources.Load("Prefabs/Objects/AsteroidL");
  5.                 TNManager.Create(obj, new Vector3(0, 0, 20), transform.rotation, true);
How can i prevent this effect? Do I need to implement some kind of "createStuff"-flag for every channel and set it to false after executing it once?! What will happen when everybody leaves the channel a another client relogs? Is there any way to manage/store this on the server and query it when every client tries to execure this code, otherwise each joining client won't know if it must create the gameobject or not.


Edit 2: Next question - "Persistent"/static player object.
My player switches from the game- to the galaxymap-channel. There he selects another star system and then goes back to the game-channel. How can I get the information about the selection or player information in general from channel to channel? I thought the TNNamager.Plaers.Data would be the way to go, but this class wont do the job since the actual player isnt contained in the list. I also tried the GamePlayer-Object from the tutorial (static variable), but that doesnt seem to work either, after switching the scenes, all values in my GamePlayer-Object are lost...
This is my player-Object:
  1. public class ActPlayer : MonoBehaviour {
  2.        
  3.         static public ActPlayer instance;
  4.        
  5.         public StarSystem selectedSystem;
  6.         public Vector3 playerPosition;
  7.  
  8.         void Awake ()
  9.         {
  10.                 if (TNManager.isThisMyObject) {
  11.                         instance = this;
  12.                 }
  13.         }
  14. }

And this is how I want to retrieve the value:
  1. public class SysUpdateSelText : MonoBehaviour {
  2.         public GUIText actSelGalMap;
  3.  
  4.         // Update is called once per frame
  5.         void Update () {
  6.                 if (ActPlayer.instance.selectedSystem != null) {
  7.                         actSelGalMap.text = ActPlayer.instance.selectedSystem.sysName;
  8.                 } else {
  9.                         actSelGalMap.text = "No selection";
  10.                 }
  11.         }
  12. }
The ActPlayer.cs is attached to the scenes main cameras.

Thanks again for your help ArenMook, I really appreciate your work!
« Last Edit: August 25, 2014, 01:43:35 PM by DocEvil »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #3 on: August 26, 2014, 03:40:30 AM »
Don't do anything in Awake.

Have a script attached to some game object in your channel. It can be your player ship or just a random game object. Have OnNetworkJoinChannel (bool, string) function on it. Inside this function check -- are there asteroids present? If so, do nothing. If not, then you're the first person to arrive here. Check again -- is TNManager.isHosting? Yes? Great, let's spawn the asteroids.

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #4 on: August 30, 2014, 06:29:30 AM »
It's still not working. I have a script attached to my game scene. When a player joins the channel, it checks if an empty GameObject called IsSystemInitialized is existing. If not, it creates one.
I log in and the GameObject is created. Then I sign off and on again, but the object is gone and will be created a second time:

  1. public class SysTriggerSystemGeneration : MonoBehaviour {
  2.  
  3.         void OnNetworkJoinChannel ( bool success, string message)
  4.         {
  5.                 Debug.Log ("Player joined channel " + TNManager.channelID);
  6.  
  7.                 GameObject g = (GameObject)GameObject.Find ("IsSystemInitialized");
  8.                 int channelID = TNManager.channelID;
  9.                 Debug.Log("Looking for IsSystemInitialized...");
  10.                 if (g == null) {
  11.                         Debug.Log("... not found");
  12.  
  13.                         if (TNManager.isHosting) {
  14.                                 Debug.Log("I am host, crating flag");
  15.                                 GameObject isInit = (GameObject)Resources.Load("Prefabs/Tools/IsSystemInitialized");
  16.                                 isInit.name = "IsSystemInitialized";
  17.                                 TNManager.Create(isInit, true);
  18.                                 Debug.Log("Done.");
  19.                         }else {
  20.                                 Debug.Log("No initialized, but I may not create it...");
  21.                         }
  22.  
  23.                 } else {
  24.                         Debug.Log("... found! Star System is already existing");
  25.                 }
  26.         }
  27. }

The only thing that cought my eye is the name of the created GameObject: "IsSystemInitialized(Clone)". I tried to find that name, too and tried to rename it to "IsSystemInitialized" during generation - no effect.
When I join the channel with a second player, it wont find the flag and finish in the else branch of "if (TNManager.isHosting)": "No initialized, but I may not create it..."

What am I doing wrong? It seems, the network Object isnt transmitted?

Thanks again for all your help, I will never get this running without you I guess...

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #5 on: August 30, 2014, 09:51:04 AM »
Use TNManager.Create("Prefabs/Tools/IsSystemInitialized", true);

Also... you can just set an RFC call if you're trying to set some flag. Assuming your scene manager is TNBehaviour, and is on a TNObject that has a static ID that exists in the scene (and is not created via TNManger.Create), you can just set a flag via an RFC.
  1. if (!mCreated) tno.Send("CreateScene", Target.AllSaved);
  1. [RFC] void CreateScene () { mCreated = true; }

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #6 on: August 31, 2014, 06:05:43 AM »
I attached the TNObject-Script to my Flag-Gameobject and instantiated it via TNManager.Create("Prefabs/Tools/IsSystemInitialized", true);.

I now expect the server to save this object in its channel, regardless if a player is actually in the channel or not.

When I log in a first player, the flag-object is created. When a second player logs in, he is able to find the flag and knows that the system doenst need to be generated - just the way i expect it to be.

But then I log both players off (close the clients), and log a player in again: the flag-object is not found and the system will be creatad *sigh* shouldnt the server keep the channels gameobjects intact? I dont get it :-(
« Last Edit: August 31, 2014, 06:27:10 AM by DocEvil »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #7 on: August 31, 2014, 03:30:40 PM »
The channel must be created with a persistent flag as well. Otherwise last player leaving the channel effectively destroys it.

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #8 on: September 01, 2014, 02:51:27 AM »
Aaah, sure... I used the autoJoin-script. It works! GREAT, thanks!  :D Now I can finally start implement the actual gameplay.

According to your info, TNnet is able to save the server state and reload it. Can you point me to a tutorial, snippet or class-ref?


ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #9 on: September 01, 2014, 02:43:06 PM »
TNServerInstance.Start takes a filename to load. TNServerInstance.Stop takes filename to save into.

You can also save while the game is running, but only in the upcoming version (that's currently in the Pro repository).

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #10 on: September 08, 2014, 02:14:43 PM »
Hey ArenMook,

now I ran into another issue. I created some 'roids from prefabs and now wanted to change their ore-types and scale. Since I cant manipulate the uncreated gameobject and cant get hold on the created one, I attached a script to the asteroid prefab that determines a random ore type and loads a material.

First I had different roid-types for multiple players, so I checked for TNManager.IsThisMyObject before touching anything. Result: the owner now has fine roids of different materials and scales, and all other players just see default scale 1 asteroids. I then tried to attach the autosync script to the roids, but then all roids for the other player were completely gone...

I guess I need to use some kind of one-time-RPC after changing material and scale? Can you once again point me in the right direction please?

Thanks again!
Malte

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Best way to design my network functionality
« Reply #11 on: September 08, 2014, 11:01:24 PM »
You should be using a custom creation function -- RCCs to pass custom parameters. Check the sticky post:
http://www.tasharen.com/forum/index.php?topic=5416.0

DocEvil

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Best way to design my network functionality
« Reply #12 on: September 09, 2014, 01:26:04 AM »
 :o Thanks, that is exactly what I need!