Funkey
Funkey4mo ago

Difference between avatar.ownerIDInHierarchy, avatar.ownerIDSelf, and avatar.realtime.clientID?

I'm trying to keep track of the ID of the current client as clients leave and enter the room. I'm finding that avatar.owner.IDSelf always returns -1. avatar.ownerIDInHierachy seems to work but if someone leaves, and rejoins they get assigned to ID 0 even though the former client that had the ID of 1 also gets set to the ID of 0. This causes errors with my system that isn't expecting two clients to both have the ID of 0. avatar.realtime.clientID seems to work but never reassigns the ID's when someone leaves. For example if a room has two clients and client 0 leaves. Client 1 remains as ID 1 but once the client that left, rejoins the game. Their ID gets set to 0. Which ID system should I use for a system that expects unique ID's for each client and can handle clients leaving and joining without assigning duplicate ID's?
19 Replies
kapa.ai
kapa.ai4mo ago
Hi @Funkey. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The avatar.ownerIDSelf property returns the client ID of the component owner. If the component is not owned by any client, it returns -1. This is why you're seeing -1 when you try to access this property. The avatar.ownerIDInHierarchy property returns the client ID of the component's hierarchy owner (the root owner of the component). This means that if a client owns a parent component, all child components will return the parent's client ID when ownerIDInHierarchy is accessed. The avatar.realtime.clientID property returns the client ID assigned by the server when the client connects to the room. This ID is unique for each client and remains the same for the duration of the client's connection. If a client disconnects and then reconnects, they will be assigned a new client ID. If you need a system that assigns unique IDs to each client and can handle clients leaving and joining without assigning duplicate IDs, you should use avatar.realtime.clientID. This property will always return a unique ID for each client, regardless of whether they disconnect and reconnect. However, please note that in offline mode, Realtime.clientID and Room.clientID will always return 0. Also, if two instances of Realtime or Room connect to the same offline mode room name, they will have separate instances that do not share any data or state. Sources: - RealtimeModel (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeModel) - RealtimeComponent (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeComponent%601) - IRealtimeComponent (https://normcore.io/documentation/reference/classes/Normal.Realtime.IRealtimeComponent) - Offline Mode (https://normcore.io/documentation/room/offline-mode#things-to-know) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below
Funkey
Funkey4mo ago
@Normcore Assistant If I want a system that reassigns client ID's when someone leaves, should I just not use it? I notice that if a client leaves, the ID's don't get reassigned. E.g client 0 leaves and everyone ID's remains the sames. But if someone new joins, they get assigned to client 0 which isn't ideal for my logic.
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The behavior you're observing is expected. In NormalVR's system, when a client disconnects, their ID is not reassigned to another client. Instead, it's freed up and can be assigned to a new client that connects to the room. This is why you're seeing a new client get assigned the ID of a client that has disconnected. If you need a system that reassigns client IDs when a client disconnects, you might need to implement this logic yourself. You could create a manager that keeps track of all connected clients and their IDs. When a client disconnects, the manager could reassign their ID to another client. However, please note that this could lead to complications, especially if you're using the client ID to keep track of state or data associated with a client. If a client's ID changes, any state or data associated with their old ID would need to be updated to reflect their new ID. In general, it's recommended to use the client ID system provided by NormalVR, as it ensures that each client has a unique ID for the duration of their connection. If you need to keep track of clients across connections, you might want to consider using a different identifier, such as a username or a unique identifier generated when the client first connects. Sources: - RealtimeAvatarManager (https://normcore.io/documentation/realtime/xr/avatars#realtimeavatarmanager) - RealtimeComponent (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeComponent%601) - IRealtimeComponent (https://normcore.io/documentation/reference/classes/Normal.Realtime.IRealtimeComponent) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below
Mechabit
Mechabit4mo ago
realtime.clientID is your local client ID also a client's id doesn't change while they are connected, if someone leaves their ID becomes available for reuse when someone else joins, you wont necessarily get the same id if you leave and rejoin. the key value in avatarmanager.avatars will be that avatar's client id, you can use that.
maxweisel
maxweisel4mo ago
and it’s not possible for two connected clients to have the same clientID if you need your own GUID, store it on a custom model/component on the avatar
Funkey
Funkey4mo ago
Sounds good! Thank you for the help! @Normcore Assistant Sorry if this question seems trivial, but RealtimeAvatarManager.avatars[realtime.clientID] will be set to null if there is no avatar with the realtime.clientID that's used as the index into the avatars dictionary. Is that correct?
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you are correct. The RealtimeAvatarManager.avatars is a dictionary that maps client IDs to their corresponding RealtimeAvatar instances. If you try to access an avatar using a client ID that does not exist in the dictionary (i.e., there is no avatar with that client ID), it will return null. Here's how you might access an avatar from the dictionary:
RealtimeAvatar avatar = RealtimeAvatarManager.avatars[realtime.clientID];
if (avatar == null) {
// There is no avatar with the given client ID.
}
RealtimeAvatar avatar = RealtimeAvatarManager.avatars[realtime.clientID];
if (avatar == null) {
// There is no avatar with the given client ID.
}
In this code, RealtimeAvatarManager.avatars[realtime.clientID] will be null if there is no avatar with the realtime.clientID that's used as the index into the avatars dictionary. Source: RealtimeAvatarManager (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.ai4mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below
Funkey
Funkey4mo ago
@Normcore Assistant
for(i=0;i<6; i++){
Debug.Log(avatarManager.avatars[i]);
}
for(i=0;i<6; i++){
Debug.Log(avatarManager.avatars[i]);
}
C# This has a single client and I get an key not found error for i=1, which makes sense. I'm assuming that there is no null set to the avatars dictionary, it appears that a clientID will create a key value pair once someone joins. I'm assuming if someone leaves such as client 0 leaving, then the value will either be set to null or the key|value pair is removed from the avatars dictionary. Is that correct?
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you are correct. The RealtimeAvatarManager.avatars dictionary maps client IDs to their corresponding RealtimeAvatar instances. When a client joins the room, a new key-value pair is added to the dictionary with the client's ID as the key and their avatar as the value. When a client leaves the room, their avatar is destroyed and the corresponding key-value pair is removed from the avatars dictionary. This is why you're getting a KeyNotFoundException when you try to access an avatar using a client ID that no longer exists in the dictionary. Here's how you might safely access an avatar from the dictionary:
RealtimeAvatar avatar;
if (RealtimeAvatarManager.avatars.TryGetValue(realtime.clientID, out avatar)) {
// Avatar found!
} else {
// There is no avatar with the given client ID.
}
RealtimeAvatar avatar;
if (RealtimeAvatarManager.avatars.TryGetValue(realtime.clientID, out avatar)) {
// Avatar found!
} else {
// There is no avatar with the given client ID.
}
In this code, RealtimeAvatarManager.avatars.TryGetValue(realtime.clientID, out avatar) will return false and avatar will be null if there is no avatar with the realtime.clientID that's used as the key into the avatars dictionary. Source: RealtimeAvatarManager (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.ai4mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below
Funkey
Funkey3mo ago
@Normcore Assistant How does RealtimeAvaterManager.avatars.count work? Will it give me the proper headcount of players in the game or should I just loop through it and check the non null objects?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The RealtimeAvatarManager.avatars.count property will give you the number of key-value pairs in the avatars dictionary, which corresponds to the number of avatars (or players) currently in the room. Each key-value pair represents a client and their corresponding avatar. When a client joins the room, a new key-value pair is added to the dictionary. When a client leaves the room, their avatar is destroyed and the corresponding key-value pair is removed from the dictionary. Therefore, avatars.count should give you the correct number of players in the room at any given time. Here's how you might use it:
int playerCount = RealtimeAvatarManager.avatars.Count;
Debug.Log("Number of players in the room: " + playerCount);
int playerCount = RealtimeAvatarManager.avatars.Count;
Debug.Log("Number of players in the room: " + playerCount);
In this code, RealtimeAvatarManager.avatars.Count will give you the number of players currently in the room. You don't need to loop through the dictionary and check for non-null objects. If a client leaves the room, their key-value pair is removed from the dictionary, so there should not be any null objects in the dictionary. Source: RealtimeAvatarManager (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.ai3mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below
Funkey
Funkey3mo ago
@Normcore Assistant For some reason, someone joining and leaving increases the player count. Like a two player game, and player 2 leaves and rejoins now makes that count 3 for some reason.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- That's unusual. The RealtimeAvatarManager.avatars.Count should reflect the current number of players in the room. If a player leaves and rejoins, the count should remain the same, not increase. When a player leaves the room, their avatar is destroyed and the corresponding key-value pair is removed from the avatars dictionary. When the player rejoins, a new key-value pair is added to the dictionary. This should not increase the total count. Here's a simple way to print the current player count whenever it changes:
using UnityEngine;
using Normal.Realtime;

public class PlayerCountLogger : MonoBehaviour {
private RealtimeAvatarManager _avatarManager;

private void Awake() {
_avatarManager = GetComponent<RealtimeAvatarManager>();
_avatarManager.avatarCreated += AvatarCreated;
_avatarManager.avatarDestroyed += AvatarDestroyed;
}

private void AvatarCreated(RealtimeAvatarManager avatarManager, RealtimeAvatar avatar, bool isLocalAvatar) {
Debug.Log("Player joined. Current player count: " + avatarManager.avatars.Count);
}

private void AvatarDestroyed(RealtimeAvatarManager avatarManager, RealtimeAvatar avatar, bool isLocalAvatar) {
Debug.Log("Player left. Current player count: " + avatarManager.avatars.Count);
}
}
using UnityEngine;
using Normal.Realtime;

public class PlayerCountLogger : MonoBehaviour {
private RealtimeAvatarManager _avatarManager;

private void Awake() {
_avatarManager = GetComponent<RealtimeAvatarManager>();
_avatarManager.avatarCreated += AvatarCreated;
_avatarManager.avatarDestroyed += AvatarDestroyed;
}

private void AvatarCreated(RealtimeAvatarManager avatarManager, RealtimeAvatar avatar, bool isLocalAvatar) {
Debug.Log("Player joined. Current player count: " + avatarManager.avatars.Count);
}

private void AvatarDestroyed(RealtimeAvatarManager avatarManager, RealtimeAvatar avatar, bool isLocalAvatar) {
Debug.Log("Player left. Current player count: " + avatarManager.avatars.Count);
}
}
If you're still seeing the player count increase when a player leaves and rejoins, there might be an issue with how avatars are being managed in your game. You might want to check your code to make sure avatars are being properly destroyed when a player leaves, and that a new avatar is only created when a player joins. Source: RealtimeAvatarManager (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.ai3mo ago
<@304126447302344705> kapa.ai is still learning and improving, please let us know how it did by reacting below