Issue with "IPlayer.SetProperty" and "IPlayer.SetProperties"

Hello everyone :grinning:,

I am working on a lobby system for a multiplayer game and would like to implement an “IsReady” functionality. The idea is to let players toggle their ready state, and once all players are marked as “ready,” the game can start.

I planned to achieve this using player properties (IPlayer.SetProperty and IPlayer.SetProperties), assuming that these updates would trigger the ISession.PlayerPropertiesChanged event. However, I noticed that when I call SetProperty to update a player’s property, the event is not triggered.

I’m not sure if I am misunderstanding how SetProperty and PlayerPropertiesChanged are supposed to work, or if there is an issue in my implementation.

If not, what would be the recommended approach to sync player states (like “ready” status) across the lobby?
Any insights or examples of similar implementations would be greatly appreciated!

Thanks in advance for your help.

Post your implementation. :wink:

Yes, you’re right, I’ll detail my implementation.

I based my work on the Multiplayer Widgets published by Unity. I reused a significant portion of the code, particularly for session creation. Here’s an overview:

var sessionOptions = new SessionOptions
{
    MaxPlayers = enterSessionData.MaxPlayers,
    IsLocked = false,
    Password = enterSessionData.Password,
    PlayerProperties = playerProperties,
    Name = enterSessionData.SessionAction == SessionAction.Create
        ? enterSessionData.SessionName
        : Guid.NewGuid().ToString()
};

I also define the player’s initial properties when joining or creating a session. This includes properties like the player’s name and a flag for their “ready” state:

private static async Task<Dictionary<string, PlayerProperty>> GetPlayerProperties()
{
    var playerName = await Unity.Services.Authentication.AuthenticationService.Instance.GetPlayerNameAsync();

    var playerNameProperty = new PlayerProperty(playerName, VisibilityPropertyOptions.Member);
    var isReadyProperty = new PlayerProperty("false", VisibilityPropertyOptions.Member);

    var playerProperties = new Dictionary<string, PlayerProperty>
    {
        { "PlayerName", playerNameProperty },
        { "IsReady", isReadyProperty }
    };

    return playerProperties;
}

To manage the “ready” state, I implemented this function, which updates the player’s properties dynamically. It toggles the “IsReady” state between true and false. WithSetProperties:

    private void UpdatePlayerReadyState()
    {
        lobby.Session.ActiveSession.CurrentPlayer.Properties.TryGetValue("IsReady", out var isReadyPropertyValue);

        var newIsReadyPropertyValue = isReadyPropertyValue is { Value: "true" } ? "false" : "true";

        var updatedProperties = new Dictionary<string, PlayerProperty>(lobby.Session.ActiveSession.CurrentPlayer.Properties)
        {
            ["IsReady"] = new PlayerProperty(newIsReadyPropertyValue, VisibilityPropertyOptions.Member)
        };

        lobby.Session.ActiveSession.CurrentPlayer.SetProperties(updatedProperties);
    }

Another implementation wthSetProperty:

    private void UpdatePlayerReadyState()
    {
        lobby.Session.ActiveSession.CurrentPlayer.Properties.TryGetValue("IsReady", out var isReadyPropertyValue);

        var newIsReadyPropertyValue = isReadyPropertyValue is { Value: "true" } ? "false" : "true";

        var isReadyNewProperty = new PlayerProperty(newIsReadyPropertyValue, VisibilityPropertyOptions.Member);
        lobby.Session.ActiveSession.CurrentPlayer.SetProperty("IsReady", isReadyNewProperty);
    }

This is a temporary implementation for testing purposes.
The properties are correctly updated locally but not on the server side.

Multiplayer Services: 1.0.2
Network Topology: Distributed Authority
Protocol Type: Unity Transport

Do you perhaps have to “send” or sync these changes? According to the docs this sounds to be the case:

SavePlayerDataAsync(string)

Save the updated properties of a player.

This call, any service call for that matter, can fail. It will throw an exception that you need to handle otherwise any time Internet drops or the service is down your script would stop to function. Try/catch any and all service calls and handle exceptions appropriately because they WILL occur often enough that you can’t publish without error handling!

Also add a using to shorten such lines:

using Unity.Services.Authentication;
1 Like

Hello,

That’s exactly it!
I wasn’t calling SavePlayerDataAsync(). I feel a bit silly for missing that in the documentation :sweat_smile:.
Thank you so much for your help and for the advice, which I will definitely apply!

1 Like