Mikameel
Mikameel5d ago

Networked player names design pattern

I want to use player names to log scores. I want each player to have a name that is set locally before joining any realtime session. I want to store that name to player prefs. when a player joins a session, I want their name to be shown in a textmeshpro line above their head. What is a good model example for this?
2 Replies
kapa.ai
kapa.ai5d ago
Hi @Mikameel. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To implement networked player names with the design pattern you described using NormalVR (Normcore), we can create a custom RealtimeComponent to synchronize player names. Here's a high-level approach based on the information provided in the knowledge sources: 1. Create a custom RealtimeComponent for player names: First, create a new script called PlayerNameSync.cs that inherits from RealtimeComponent. This component will be responsible for synchronizing the player's name across the network.
using Normal.Realtime;
using TMPro;
using UnityEngine;

public class PlayerNameSync : RealtimeComponent<PlayerNameSyncModel>
{
[SerializeField] private TextMeshPro nameText;

private void Awake()
{
// Load the player name from PlayerPrefs
string playerName = PlayerPrefs.GetString("PlayerName", "Player");
}

protected override void OnRealtimeModelReplaced(PlayerNameSyncModel previousModel, PlayerNameSyncModel currentModel)
{
if (currentModel != null)
{
if (currentModel.isFreshModel)
{
// Set the initial name when the model is fresh
currentModel.name = PlayerPrefs.GetString("PlayerName", "Player");
}

// Update the TextMeshPro component
UpdateNameText();

// Subscribe to name changes
currentModel.nameDidChange += NameDidChange;
}

if (previousModel != null)
{
// Unsubscribe from the previous model's events
previousModel.nameDidChange -= NameDidChange;
}
}

private void NameDidChange(PlayerNameSyncModel model, string value)
{
UpdateNameText();
}

private void UpdateNameText()
{
if (nameText != null)
{
nameText.text = model.name;
}
}
public void SetPlayerName(string newName)
{
// Update the model
model.name = newName;

// Save to PlayerPrefs
PlayerPrefs.SetString("PlayerName", newName);
PlayerPrefs.Save();
}
}
using Normal.Realtime;
using TMPro;
using UnityEngine;

public class PlayerNameSync : RealtimeComponent<PlayerNameSyncModel>
{
[SerializeField] private TextMeshPro nameText;

private void Awake()
{
// Load the player name from PlayerPrefs
string playerName = PlayerPrefs.GetString("PlayerName", "Player");
}

protected override void OnRealtimeModelReplaced(PlayerNameSyncModel previousModel, PlayerNameSyncModel currentModel)
{
if (currentModel != null)
{
if (currentModel.isFreshModel)
{
// Set the initial name when the model is fresh
currentModel.name = PlayerPrefs.GetString("PlayerName", "Player");
}

// Update the TextMeshPro component
UpdateNameText();

// Subscribe to name changes
currentModel.nameDidChange += NameDidChange;
}

if (previousModel != null)
{
// Unsubscribe from the previous model's events
previousModel.nameDidChange -= NameDidChange;
}
}

private void NameDidChange(PlayerNameSyncModel model, string value)
{
UpdateNameText();
}

private void UpdateNameText()
{
if (nameText != null)
{
nameText.text = model.name;
}
}
public void SetPlayerName(string newName)
{
// Update the model
model.name = newName;

// Save to PlayerPrefs
PlayerPrefs.SetString("PlayerName", newName);
PlayerPrefs.Save();
}
}
2. Create a corresponding model for the PlayerNameSync component: Create a new script called PlayerNameSyncModel.cs:
using Normal.Realtime;
using Normal.Realtime.Serialization;

public class PlayerNameSyncModel : RealtimeModel
{
[RealtimeProperty(1, true)]
public string name;
}
using Normal.Realtime;
using Normal.Realtime.Serialization;

public class PlayerNameSyncModel : RealtimeModel
{
[RealtimeProperty(1, true)]
public string name;
}
3. Add the PlayerNameSync component to your player avatar prefab: Attach the PlayerNameSync component to your player avatar prefab and assign the TextMeshPro component for displaying the name above the player's head. 4. Set the player name before joining a session: Before connecting to a room, you can set the player's name using PlayerPrefs:
PlayerPrefs.SetString("PlayerName", "YourPlayerName");
PlayerPrefs.Save();
PlayerPrefs.SetString("PlayerName", "YourPlayerName");
PlayerPrefs.Save();
5. Connect to the room: Use the Realtime component to connect to a room as described in the Realtime documentation:
_realtime.Connect("RoomName");
_realtime.Connect("RoomName");
This approach follows the pattern described in the Synchronizing Custom Data documentation. It uses a custom RealtimeComponent to synchronize the player's name across the network, stores the name in PlayerPrefs for persistence, and displays it using a TextMeshPro component above the player's head. Remember to add the PlayerNameSync component to your list of RealtimeComponents in the RealtimeView on your player avatar prefab. This solution should provide a good starting point for implementing networked player names in your NormalVR (Normcore) project. You can expand on this to include additional functionality, such as updating scores associated with player names. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@365574199844274177> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?