Hello, Unity Community.
I want to make an online event with a help of Mirror, where players register for an event, and plays there own game till event finishes, when event finishes I need to update SyncVar of all players who register for an event. SyncVar mode Owner only.
At the moment when I register for event I save netID. Is there a way to find specific player object and update SynVar if I know netID?
Or should I save something else if I want to access specific player Object at any time from server?
One option is to have the server keep a list of all players in an event, and when the event ends send a TargetRpc to each player with the values you want to update.
If this is really a single player game, then staying connected to a mirror based server the whole time doesnât even sound necessary. You could have clients connect, and register for the event. When registering the client provides some information like playerâs name, and server generates a kind of token for the client. Like just a random long, and provides that to the client. Then the client disconnects and plays the single player game.
At the end of each clientâs game, it reconnects to the server, provides both the username and token, along with the gameâs results.
If I am right by doing so I will be able to access any player game object at any time.
In my eyes Mirror should have some think like this already build in. But I canât find it in documentation.
Didnât have time to test it yet, donât know if it will work
Iâm not sure on getting gameobjects by their netId as Iâve not looked into it. If you do want to use a pre-existing identifier the playerâs connectionId is another option. You can get this on the server with player.connectionToClient.connectionId.
Ignoring an id look up, in its simplest form you could make a call like this from the player:
[Command]
public void CmdRegisterForEvent(EventType eventType)
{
EventManager.Instance().RegisterPlayerForEvent(eventType, this);
}
You might want to track a player outside of the network values, if they get disconnected and reconnect for example. Perhaps something to think about further down the line.
AA now I get it. In my idea You quit the game no event for You. As I planning, it there wont be even a scene change. Thatâs why I need to notify player in real time.
I am not getting SyncVar Hook triggered and SyncVar Updated, donât know if I am doing Right.
Each player when he join games:
public override void OnStartClient()
{
if (!isLocalPlayer) { return; }
uint id = NetworkClient.localPlayer.netId;
NetworkIdentity networkIdentity = NetworkClient.connection.identity;
CmdplayerLogin(id, this);
}
[Command]
void CmdplayerLogin(uint id, playerOBJ pp)
{
if (isServer)
{
player p = new player
{
playerOBJ = pp,
playerID = id,
nickName = "QQ" + id.ToString(),
coinsTotal = 200000,
tableID = 0,
coinsAtTable = 0
};
player = p;
serverStart.ServerPlayers.Add(p);
}
}
-public class player {
public playerOBJ playerOBJ;
public bool eventRegistration;
public bool eventStart;
public uint playerID;
public string nickName;
public int tableID;
public int tableChair;
public int joinedListIndex;
public float coinsTotal;
public float coinsAtTable;
}
playerOBJ itâs a script that is added to Player prefab and it contains all the syncvarsâŚ
now lets just say I need 5 players to register for an event. Registration starts like so:
[Command]
void CmdRegisterPlayerToEvent() {
if (serverStart.ServerPlayers.Count() < 5)
{
addPlayerForEvent();
}
if (serverStart.ServerPlayers.Count() == 5)
{
for (int i = 0; i < serverStart.ServerPlayers.Count(); i++)
{
if (serverStart.ServerPlayers[i].playerOBJ.player.eventRegistration)
{
serverStart.ServerPlayers[i].playerOBJ.player.eventStart = true;
}
}
}
}
After that there is a hook that should be triggered when I update serverStart.ServerPlayers*.playerOBJ.player SyncVar, but itâs not triggered.* csharp* *[SyncVar(hook = nameof(playerDataChanged))] public player player = new player();* * csharp* *private void playerDataChanged(player oldP, player newP) { Debug.Log("Triggered"); }* * Any idea what I am doing wrong?
You donât need to pass the player to CmdplayerLogin (actually it might not work as intended), instead use âthisâ within the method, as that code is running on the serverâs copy of the player. I donât know if thatâs the issue but itâs a place to start.
player p = new player
{
playerOBJ = this,
playerID = id,
nickName = "QQ" + id.ToString(),
coinsTotal = 200000,
tableID = 0,
coinsAtTable = 0
};
playerOBJ gets updated only on host but not on clients.
Maybe I am not getting the right result because I create a Copy of playerOBJ not a reference to original? It should be so simple task and I stuck here for two days
Does the hook get called? Youâll likely want to have SyncVar on all the fields in the player class that you want to update on the client. To be honest I havenât used syncvars so much as for what Iâm doing it was more convenient to create my own message services.
I was wondering though why you have a separate player class and not just have those fields on playerOBJ?
No the hook did get triggered.
I can see it only on update function:
private void Update()
{
if (!isLocalPlayer) { return; }
if (player.eventStart) {
Debug.Log("True");
}
}
I have SyncVar player on playerOBJ, where I store data about player.
And I have a List joinedPlayers on server only, where I store everything about all players on a server. That helps me track everything.
I donât think you can use object references to tie objects together between client and server, so you may well be ending up with a new playerOBJ on the client.
I donât understand what do You mean: âadding an extra layer of complexity using the player class rather than have those fields on playerOBJâ. I am not that good with programing just learning
ClientRPC will send message to all players on a server, thatâs the worst case scenarios for me.
Target RPC wont be same as SyncVar? Can I identify players connection somehow?
I mean you can just use playerOBJ and do away with the âplayerâ class, it looks to contain values integral to the player and should be on the playerOBJ.
A little advice on class names, itâs best to follow convention and start class names with capitals. If youâre using a decent IDE like Visual Studio or Visual Code they should be giving hints as guidance. Iâd just go with Player for the playerâs prefab/script, playerOBJ is misleading as itâs a class not an object.
If youâre learning programming + Unity + multiplayer thatâs a real steep learning curve, I would suggest not worrying about multiplayer for now as you might find it overwhelming trying to learn it all at once.
Well most of my programing was with PHP⌠php class that stores variables, arrays etc⌠we call Objects. https://www.tutorialspoint.com/php-objects
playerOBj class stores all the information about player and the game that surrounds him. For me is natural to call it obj
player class is just a helper class that helps to construct SyncVar player for playerOBj and serverOBj there is a list of players there is no mono/network behavior
Go with what youâre comfortable with, but itâs best to follow conventions. If nothing else it makes the code more readable. It will also be beneficial to use descriptive naming to make the code self-commenting. At a glance I canât see the difference in responsibility between the player and playerOBJ classes.
I think the player class is more a hindrance than a help but if youâre going to stick with it one thing I wanted to mention was that the playerOBJ field is only relevant on the server so I would avoid using it on the client.