Author Topic: Beginner question: clients create own players or host sends data  (Read 11616 times)

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Hi.

I'm a beginner with TNet and have some questions regarding the creation of the player objects. Currently I'm trying to understand how data is shared between the different clients and the server.

In my case I have a two player battle logic which should be the same for both player (no Unity representation yet). The data of the battle should be used by both players to create the player representations and the battle field itself (also the Unity representations of them).

Now I don't understand exactly how this could be done yet. I've achieved it that the players could send to the server that they are joining the game and the Unity representations are correctly created. But I have problems to check if they are the player on the left or on the right side. This should be in no fix order when to join, so I have to somehow find out if they are the left or the right player.

So...
1.) How can I distribute this battle data to all joined players? And how do I get notice that I got this data and which kind of data it is?

  1. public class BattleData
  2. {
  3.    public GamePlayer playerLeft;
  4.    public GamePlayer playerRight;
  5.    public BattleField battleField;
  6. }
  7.  

2.) How can I tell the server (and other player) that I'm the left player that other joined players get the information that there is a leftPlayer and the other player knows that he will be the right player? I think I would also just send a data object to the server and the server tells all clients that there is a new player joined. Or I just send a request to the server and the server knows the battle data, creates a new data object and sends it to the client.

  1. public class GamePlayer
  2. {
  3.    public BattleSide side;
  4.    public string name;
  5. }
  6.  

Am I on the right way or do I get something totally wrong?

Thx for help!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #1 on: March 16, 2014, 12:54:05 PM »
TNet's supported list of data is limited: http://www.tasharen.com/forum/index.php?topic=8475.msg40107#msg40107

You need to send your data via types it understands, or by serializing your data into a stream and then sending bytes[]. When receiving data, convert those bytes into a stream and read the data back.

It's often best to send types TNet understands so you don't have to do any extra conversion or deal with streams. For example:
  1. tno.Send("JoinTeam", Target.AllSaved, teamID);
...where 'teamID' is an integer -- can be an index of the team within a fixed size array that everyone has, instead of having "BattleSide side". Although if BattleSide is an enum, you can just send it as well by converting it to an integer.

You need to think of how to structure your game so you can send the least amount of data possible. Make sure every player has the data they need from the start, and send only identifiers/indices rather than entire structs of data. This is good practice in general, and not just with TNet.

Also note that TNManager.playerName is your player name. No need to have the 'name' field in your GamePlayer class.

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #2 on: March 16, 2014, 01:09:06 PM »
Ok thanks Aren.

This answer and Custom Object Creation functions is helping me a lot for now. I'll try to change the setup of my battle now and see how far I can get with it.

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #3 on: March 19, 2014, 03:20:21 AM »
Ok, I could do most of my stuff and it's working. Still I used Custom Packets for this and maybe this is now the problem I encouter: When players are sending that a player representation should be created for them, only the host is able to use them (i.e. TNObject.isMine is false for other players except the host).

As I'm sending only the data of the player and send create the GameObject out of the data, how can I assign the GameObject to the creating player? Can I do something like this:

  1. private void OnPlayerCreate(Packet response, BinaryReader reader, IPEndPoint source)
  2. {
  3.    var playerId = reader.GetInt32();
  4.    var newPlayer = Instantiate(playerPrefab);
  5.    newPlayer.GetComponent<TNObject>().playerID = playerId;
  6. }
  7.  

I tried that but it's not working sadly, though the host now only has control over one player. So the question is how could I assign (correctly) the playerId to the TNObject manually and should I do it this way? I thought about using the CreateEx function, as this would assign the playerId automatically as I understand. I would just have to give the same parameters to this function then as I'm giving in my own custom request.

Update:
I changed my code to use the CreateEx function, but still I have the problem that only one player can control the objects. Furthermore now I have the problem that only the last object could be controlled.

For creating the player I use this function of my BattleMgr (doesn't have a TNObject component assigned as I think I don't need one on that):
  1.     private void CreatePlayer(Player playerData, string side, string characterName)
  2.     {
  3.         Debug.Log("create player for side: " + side);
  4.         TNManager.CreateEx(1, true, playerMarker.cachedGameObject, side, characterName, );
  5.     }
  6.  
  7.     [RCC(1)]
  8.     private void CreatePlayerForClient(GameObject prefab, string battleSideString, string characterName)
  9.     {
  10.         Debug.Log("createplayerforclient");
  11.         var newPlayerMarker = Instantiate(playerMarker) as GameObject;
  12.         newPlayerMarker.transform.parent = battleElementsParent;
  13.     }
  14.  

For moving the player I use this function in my PlayerMarker MonoBehaviour script (this one has also a TNObject to it assigned):

  1. public void OnGUI()
  2. {
  3.      float xPos = 100;
  4.      if (battleSide == BattleSide.Left)
  5.           xPos = Screen.width - 100f;
  6.  
  7.      if (tno.isMine && GUI.Button(new Rect(xPos, 350, 100, 50), "up: " + tno.ownerID))
  8.      {
  9.           MovePlayer(1);
  10.      }
  11.      if (tno.isMine && GUI.Button(new Rect(xPos, 400, 100, 50), "down: " + tno.ownerID))
  12.      {
  13.           MovePlayer(-1);
  14.      }
  15. }
  16.  
  17. private void Update()
  18. {
  19.     if (tno.isMine)
  20.         playerMarker.position = playerPosition;
  21. }
  22.  
  23. private void MovePlayer(int positionChange)
  24. {
  25.     if (tno.isMine)
  26.     {
  27.         Debug.Log("move player to: " + positionChange);
  28.         var writer = TNManager.BeginSend(Packet.MovePlayerRequest);
  29.         writer.Write(positionChange);
  30.         TNManager.EndSend(true);
  31.     }
  32.     else
  33.     {
  34.         Debug.LogError("object is not mine. ismine: " + tno.isMine);
  35.     }
  36. }
  37.  
  38. private void OnMovePlayer(Packet response, BinaryReader reader, IPEndPoint source)
  39. {
  40.     if (response == Packet.MovePlayerResponse)
  41.     {
  42.         var positionChange = reader.ReadInt32();
  43.         playerPosition += positionChange;
  44.     }
  45. }
  46.  

The strange thing is that I now can only move one of the PlayerMarkers, but I assumed that I would either control both PlayerMarkers (if both players joined) or none.
« Last Edit: March 19, 2014, 05:11:52 PM by pahe »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #4 on: March 20, 2014, 02:36:42 AM »
Whichever player calls TNManager.Create is the one who will be the object's owner.

There is no need to set the owner player yourself.

Also keep in mind that you can't pass a game object as a parameter, unless this game object is on TNManager's list of known game object. If it isn't, then you need to pass a string name of the prefab, and place the prefab in the Resources folder.

Otherwise how would TNet load it?

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #5 on: March 20, 2014, 04:45:25 AM »
Ok
I' having a prefab "playerMarker" which gameObject I pass to the CreateEx function. Also this prefab is known to the TNManager that it should be known to the server then aswell.
Could it be that the prefab has to be of the type GameObject? Currently the prefab is of the type PlayerMarker which has a property cachedGameObject that I'm using in my function. Haven't thought about that.

TNet is able to create the prefabs, but I think the problem is more that the created objects are not set correctly to their owners. That's the reason why I first tried to assign the playerId by myself.
« Last Edit: March 20, 2014, 08:56:19 AM by pahe »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #6 on: March 20, 2014, 01:15:11 PM »
It has to be a game object. TNManager's list is a list of game objects. How did you reference something other than a game object there?

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #7 on: March 20, 2014, 01:32:58 PM »
It is a GameObject. I meant that in the CreatePlayer function the property is used:

  1. TNManager.CreateEx(1, true, playerMarker.cachedGameObject, side, characterName, );
  2.  

Maybe I should try a same approach as in the "Create Cube" example. I'll try that at the weekend to change it.
« Last Edit: March 21, 2014, 07:37:22 AM by pahe »

pahe

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 1
  • Posts: 37
    • View Profile
Re: Beginner question: clients create own players or host sends data
« Reply #8 on: March 23, 2014, 09:39:50 AM »
Ok, I got it nearly working, but I still have a problem:

If I'm creating the players prefab with the TNManager.Create function it's working, but I have to set the battle side later. If I use the TNManager.CreateEx function, it doesn't work, though I don't know why.

  1.     private void Awake()
  2.     {
  3.         TNManager.AddRCCs(this);
  4.         instance = this;
  5.     }
  6.  
  7.     private void OnGUI()
  8.     {
  9.         if (leftPlayer == null && GUI.Button(new Rect(100, 150, 100, 50), "create left"))
  10.             CreatePlayer("Left");
  11.         if (rightPlayer == null && GUI.Button(new Rect(100, 200, 100, 50), "create right"))
  12.             CreatePlayer("Right");
  13.     }
  14.  
  15.     private void CreatePlayer(string side)
  16.     {
  17.         //TNManager.Create(playerPrefab, false); // working
  18.         TNManager.CreateEx(10, false, playerPrefab, side); // not working
  19.     }
  20.  
  21.     [RCC(10)]
  22.     private void OnCreatePlayer(GameObject prefab, string sideString)
  23.     {
  24.         var player = Instantiate(prefab) as GameObject;
  25.         var newPlayer = player.GetComponent<TestPlayer>();
  26.         if (sideString.Equals("Left"))
  27.         {
  28.             newPlayer.InitPositions(leftSide, sideString);
  29.             leftPlayer = newPlayer;
  30.         }
  31.         else
  32.         {
  33.             newPlayer.InitPositions(rightSide, sideString);
  34.             rightPlayer = newPlayer;
  35.         }
  36.     }

This is a bit confusing to me, as I thought both functions would do similar things, except that the CreateEx function could be used for more parameters. Any guesses why the CreateEx function may not work for me?

Update: Ok, I think I forgot the GameObject as return value. Yeha! Now it works!!! :)
« Last Edit: March 24, 2014, 01:49:17 PM by pahe »