Hi, I want to know how I can synchronize Players in the order they join, and when the level is done "loading". That is, after the level is loaded, the play field is randomized in Start(), like so:
public void Start()
{
if (!TNManager.isHosting) return;
for (int row = 0; row < numberOfRows; row++)
{
for (int col = 0; col < numberOfColumns; col++)
{
if(Random
.value > 0.9) TNManager
.Create(blockObject,
new Vector3
(row,
0,col
), Quaternion
.identity); }
}
StartCoroutine(PlayerWaitSpawn() );
}
Cut the down code to what it is essentially like, it creates a random playing field each time the level is loaded. So that works fine. However, I do not know how to synchronize players properly. The two conditions I need fulfilled are
1) Wait for at least 2 players to be in the channel/level
2) Also, wait for the level to completely load, that is after the Create() functions called in Start() finish appearing for other clients
In the coroutine I start after calling the Create() functions in Start(), I tried a few things, with the closest resembling any form of success being:
First yield waits continually until TNManager.players.Count is greater than 0 (Why does this not include the host player by the way?)
Next, Spawn the host's player character (since the coroutine was called from Start() where the check ensures only the host player is doing logic, it does not create multiple characters from other clients)
Finally, in a loop, for each player send them an RFC telling them to Create() their player (So they have ownership. On a side note I spawn them in certain locations according to the order of the TNManger.players list, but this is only to simulate what I want to do mentioned further below. It won't well once players leave the level/channel in the middle of a game)
However, this does not really work well as sometimes the RFC reaches the client faster than the Create() calls from Start() apparently as the player will fall through the floor when it happens. Also, upon joining for the first time, clients do not spawn their players ever, only the host player does. The level must be reloaded via TNManager.LoadLevel() for clients to spawn players this way, and not sure why. I am not using SendQuickly() either, as it is important that the message sent be received. Note sure why I didn't just post it but here it is
IEnumerator PlayerWaitSpawn()
{
while (TNManager.players.Count == 0)
{
yield return new WaitForSeconds
(1f
); }
if (TNManager.isHosting)
{
TNManager
.Create(playerObject,
new Vector3
(0f ,0f, 0f
), Quaternion
.identity,
false); }
int lastPlayerID = 0;
foreach (Player p in TNManager.players)
{
//if (p.id > lastPlayerID) {StaticPlayerIDsDict.Add(lastPlayerID,true);}
//if (StaticPlayersIDsDict[p.id]) ...
lastPlayerID += 1;
switch(lastPlayerID)
{
case 1:
tno
.Send(99, p,
new Vector3
(numberOfRows, 0f, 0f
) ); break;
case 2:
tno
.Send(99, p,
new Vector3
(numberOfRows
/2, 0f, numberOfColumns
) ); break;
case 3:
tno
.Send(99, p,
new Vector3
(0f,0f,numberOfColumns
/2) ); break;
//etc.. will finish later
}
}
}
[RFC(99)]
void PersonalCreate(Vector3 vector)
{
TNManager.Create(playerObject, vector, Quaternion.identity, false);
}
Finally, if I get the above solved, I need to spawn players in the order they joined the channel/level (so I can spawn them in proper positions on the map, ie. the player that has second place in the room always spawns in the upper middle section of the map), and if they leave, a player must take their place (such as 2nd place of 8 players if first place, and third-eighth place is taken). I figure I could do something with the Player.id and compare the ids in the TNManager.players list and add them to a dictionary in order or something but then I don't know how to synchronize this properly or if it would even work for organizing players spawning like this.