fgamez1020
fgamez10202mo ago

Multy Player Turn System

How to build and implement a turn system to let the user know when its their turn in the game?
22 Replies
kapa.ai
kapa.ai2mo ago
Hi @fgamez1020. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Hmm, I don't know enough to give you a confident answer yet. However, I can tell you that in NormalVR, you can use the RealtimeComponent to synchronize data in your application. This could potentially be used to manage a turn system by keeping track of whose turn it is in a shared state. For example, you could create a custom RealtimeComponent subclass that stores the current player's turn in a RealtimeModel. When a player finishes their turn, they could update this model, which would then be synchronized across all clients. You can find more information on how to create a custom RealtimeComponent subclass in the NormalVR documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtimecomponent-subclass). Please note that this is a general approach and the specific implementation may vary depending on the details of your game. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1053407831916822528> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mechabit
Mechabit2mo ago
Synchronizing Custom Data | Normcore Documenation
In this guide, I’m going to walk you through how to synchronize custom data in your Unity application using custom realtime components.
Mechabit
Mechabit2mo ago
you want to store an int that says who's turn it is when that player is done they increment the int all players register for the change event when the int changes to your clientID you know it's your turn @Normcore Assistant how do you sync an int to show who's turn it is
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To synchronize an integer value representing the current player's turn in NormalVR, you would create a custom RealtimeComponent subclass that stores this value in a RealtimeModel. Here's a general approach: 1. Create a new RealtimeModel subclass that includes an integer property for the player's turn. You can use the RealtimeModel's SyncVar attribute to automatically synchronize this property across all clients. 2. Create a new RealtimeComponent subclass that uses your new RealtimeModel. In the OnRealtimeModelReplaced method, you can register for the change event of your integer property. This event will be fired whenever the property changes, allowing you to update your game state accordingly. 3. When a player finishes their turn, they would update the integer property on the model. This change would then be automatically synchronized to all other clients. Here's an example of what the RealtimeComponent subclass might look like:
using Normal.Realtime;
public class TurnSync : RealtimeComponent<TurnSyncModel> {
protected override void OnRealtimeModelReplaced(TurnSyncModel previousModel, TurnSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events on the previous model
previousModel.playerTurnDidChange -= PlayerTurnDidChange;
}
if (currentModel != null) {
// If the current model is not null, it's either a fresh model or a model that already exists
// Register for events on the new model
currentModel.playerTurnDidChange += PlayerTurnDidChange;
}
}

private void PlayerTurnDidChange(TurnSyncModel model, int value) {
// The player turn value changed, update the game state
}
}
using Normal.Realtime;
public class TurnSync : RealtimeComponent<TurnSyncModel> {
protected override void OnRealtimeModelReplaced(TurnSyncModel previousModel, TurnSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events on the previous model
previousModel.playerTurnDidChange -= PlayerTurnDidChange;
}
if (currentModel != null) {
// If the current model is not null, it's either a fresh model or a model that already exists
// Register for events on the new model
currentModel.playerTurnDidChange += PlayerTurnDidChange;
}
}

private void PlayerTurnDidChange(TurnSyncModel model, int value) {
// The player turn value changed, update the game state
}
}
In this example, TurnSyncModel would be your custom RealtimeModel subclass with a playerTurn property. The PlayerTurnDidChange method would be where you handle the change in the player's turn. You can find more information on how to create a custom RealtimeComponent subclass in the NormalVR documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtimecomponent-subclass). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@162940911964258305> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
fgamez1020
fgamez1020OP5w ago
I did what you suggested, but PlayerTurnDidChange only triggers twice and after that it does not works
Mechabit
Mechabit5w ago
you can turn off equality check to always send updates even if you set the turn index to the same number @Normcore Assistant how to turn off equality check on a model's did change event
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- In Normcore, you can disable the equality check on a model's property by setting the includeEqualityCheck argument to false when defining the RealtimeProperty. This will cause Normcore to serialize and send the value every time it's set, regardless of whether the value has changed or not. Here's an example of how to do this:
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, false, true, includeEqualityCheck: false)]
private byte[] _rawData = new byte[0];
}
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, false, true, includeEqualityCheck: false)]
private byte[] _rawData = new byte[0];
}
In this example, the _rawData property will be serialized and sent to all players every time the setter is called, even if the value hasn't changed. You can find more information on this in the Normcore documentation (https://normcore.io/documentation/room/supported-primitives#equality-checks). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@162940911964258305> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
fgamez1020
fgamez1020OP5w ago
@Normcore Assistant That did not work, the players are not being notified after the first notification
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- If the players are not being notified after the first notification, it could be due to several reasons. Here are a few things you could check: 1. Datastore Updates: All state is synchronized using the room's datastore. If you make a change to the datastore, it’s automatically replicated to all connected clients. To conserve on bandwidth, once the server has sent the initial datastore snapshot, it will only send delta updates for the remainder of the session. If your game involves a lot of state changes, this could be causing a delay in updates. source (https://normcore.io/documentation/architecture/client#datastore) 2. Server Rejections: It's also possible that the server is rejecting updates due to either ownership or Normcore Private plug-ins. When this happens, the server sends back the rejected update or a modified version of the state in the update. The datastore then rolls the data back or replaces it with the version transformed by the server. source (https://normcore.io/documentation/room/datastore#instant-updates) 3. Equality Checks: By default, when a model property is updated, Normcore will run an equality check to ensure the value has changed before sending an update to keep bandwidth use as low as possible. If you want Normcore to serialize and send a value every time it's set, regardless of whether the value has changed, you can set the includeEqualityCheck argument to false when defining the RealtimeProperty. source (https://normcore.io/documentation/room/supported-primitives#equality-checks) If none of these seem to be the issue, it might be worth reaching out to the Normcore team for further assistance. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@1053407831916822528> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
fgamez1020
fgamez1020OP5w ago
@Normcore Assistant not using real time model, how Do I send an action to an specific player?
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To send an action to a specific player in NormalVR, you can use the RealtimeAvatarManager which keeps track of all avatars in the room via the localAvatar and avatars properties. The avatars property is a dictionary of all RealtimeAvatar components stored under the clientID that the avatar belongs to. Here's an example of how you might use this to send an action to a specific player:
using UnityEngine;
using Normal.Realtime;

public class MyAvatarManager : MonoBehaviour {
private RealtimeAvatarManager _manager;

private void Awake() {
_manager = GetComponent<RealtimeAvatarManager>();
}

public void SendActionToPlayer(int clientID, YourActionType action) {
RealtimeAvatar avatar;
if (_manager.avatars.TryGetValue(clientID, out avatar)) {
// Avatar found! You can now use the avatar object to send your action.
// This will depend on how you've implemented your action system.
} else {
// Avatar not found. You may want to handle this case.
}
}
}
using UnityEngine;
using Normal.Realtime;

public class MyAvatarManager : MonoBehaviour {
private RealtimeAvatarManager _manager;

private void Awake() {
_manager = GetComponent<RealtimeAvatarManager>();
}

public void SendActionToPlayer(int clientID, YourActionType action) {
RealtimeAvatar avatar;
if (_manager.avatars.TryGetValue(clientID, out avatar)) {
// Avatar found! You can now use the avatar object to send your action.
// This will depend on how you've implemented your action system.
} else {
// Avatar not found. You may want to handle this case.
}
}
}
In this example, YourActionType would be the type of the action you're sending, and you would replace the comments with your own code to send the action to the avatar. You can find more information on the RealtimeAvatarManager in the Normcore documentation (https://normcore.io/documentation/realtime/xr/avatars#realtimeavatarmanager). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@1053407831916822528> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mechabit
Mechabit5w ago
for sending a message you create a RealtimeSet with a model that contains the target player ID and the message everything in normcore is models so you can't send anything without a model
fgamez1020
fgamez1020OP5w ago
@Normcore Assistant using the RealtimeModel I have that model with an int value that I send to all the players, I send 1 to the second player and then 0 to the first player. but when I do it again none of them get that model change
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- If you're using a RealtimeModel with an integer property and you're finding that changes to the property are not being propagated after the first change, it could be due to the equality check that Normcore performs by default. When a model property is updated, Normcore will run an equality check to ensure the value has changed before sending an update. This is done to keep bandwidth use as low as possible. If you want Normcore to serialize and send a value every time it's set, regardless of whether the value has changed, you can set the includeEqualityCheck argument to false when defining the RealtimeProperty. Here's an example:
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, false, true, includeEqualityCheck: false)]
private int _myValue;
}
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, false, true, includeEqualityCheck: false)]
private int _myValue;
}
In this example, the _myValue property will be serialized and sent to all players every time the setter is called, even if the value hasn't changed. However, please note that the includeEqualityCheck setting has no effect on nested model properties. If you're working with nested properties, you might need to manually trigger an update. You can find more information on this in the Normcore documentation (https://normcore.io/documentation/room/supported-primitives#equality-checks). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@1053407831916822528> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
fgamez1020
fgamez1020OP5w ago
@Mechabit using the RealtimeModel I have that model with an int value that I send to all the players, I send 1 to the second player and then 0 to the first player. but when I do it again none of them get that model change
Mechabit
Mechabit5w ago
if you've got this model on the player avatar you can't change models owned by other players instead you should have an unowned scene view model with the current player's turn on it and both players can edit it