Voltaia
Voltaia7mo ago

How should I handle many networked objects?

I'm concerned about performance. Essentially, I have many incredibly simple objects that need to be synced. I'm not sure if the right way to do this would be: 1. Create a RealtimeComponent and put one on each game object. 2. Create a RealtimeComponent for a manager that tracks all the objects information through a RealtimeSet or similar collection. The objects' information would each be represented by a RealtimeModel of course.
17 Replies
kapa.ai
kapa.ai7mo ago
Hi @Voltaia. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The best approach to handle many networked objects in NormalVR depends on the specific requirements of your application. However, here are some general guidelines based on the information provided in the knowledge sources: 1. RealtimeComponent on Each GameObject: This approach is straightforward and aligns with the typical use of RealtimeComponents. Each RealtimeComponent subclass is responsible for keeping a specific part of your scene in sync. The most common built-in component is RealtimeTransform, which synchronizes the transform of a GameObject. When the GameObject changes, the component updates the model, and when the model changes, the component updates the GameObject to match. This approach is efficient as Normcore model updates are designed to be as bandwidth and CPU efficient as possible. However, this might not be the most efficient approach if you have a very large number of objects, as each object would need its own RealtimeComponent and corresponding RealtimeModel. 2. RealtimeComponent for a Manager: This approach could be more efficient if you have a large number of simple objects that need to be synced. You could create a manager object with a RealtimeComponent that holds a RealtimeSet or similar collection of all the objects' information. Each object's information would be represented by a RealtimeModel. This approach could potentially reduce the number of RealtimeComponents and RealtimeModels needed, which could improve performance. Remember, each RealtimeComponent stores the state it needs to synchronize in a RealtimeModel subclass. The model is automatically synchronized across all clients by Normcore, so all the RealtimeComponent needs to do is synchronize the scene and the model to match. In conclusion, if you have a large number of simple objects, the manager approach might be more efficient. However, if each object has complex behavior or state that needs to be synced, it might be better to use a RealtimeComponent on each GameObject. Sources: - RealtimeComponent (https://normcore.io/documentation/realtime/realtimecomponent) - RealtimeModel (https://normcore.io/documentation/room/realtimemodel) - Model Change Events vs RPCs (https://normcore.io/documentation/room/common-questions#are-model-change-events-more-expensive-than-rpcs) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@276154194606424064> kapa.ai is still learning and improving, please let us know how it did by reacting below
Voltaia
VoltaiaOP7mo ago
@Normcore Assistant how should I initially populate the RealtimeComponent manager?
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- When a RealtimeComponent is first created, Normcore will create a fresh model instance in which each RealtimeComponent can store data. If the object already exists on the server, the model will be prepopulated with the current state before it is given to the RealtimeComponent. In the case of a manager RealtimeComponent, you would likely want to iterate over all the objects you want to track in the Awake() or Start() method of your manager script, and add their data to the manager's RealtimeModel. Here's a simplified example based on the ColorSync example provided in the knowledge sources:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Normal.Realtime;

public class ObjectManager : RealtimeComponent<ObjectManagerModel> {
private List<MyObject> _myObjects;

private void Awake() {
// Get references to the objects you want to track
_myObjects = new List<MyObject>(FindObjectsOfType<MyObject>());

// Populate the model with the initial state of the objects
foreach (var obj in _myObjects) {
// Add each object's data to the model
model.AddObjectData(obj.GetData());
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Normal.Realtime;

public class ObjectManager : RealtimeComponent<ObjectManagerModel> {
private List<MyObject> _myObjects;

private void Awake() {
// Get references to the objects you want to track
_myObjects = new List<MyObject>(FindObjectsOfType<MyObject>());

// Populate the model with the initial state of the objects
foreach (var obj in _myObjects) {
// Add each object's data to the model
model.AddObjectData(obj.GetData());
}
}
}
In this example, MyObject would be a script attached to each of the objects you want to track, and GetData() would be a method that returns the data you want to sync for that object. Remember, the RealtimeComponent will automatically handle syncing the model data across all clients. All you need to do is keep the scene and the model in sync. Sources: - RealtimeComponent (https://normcore.io/documentation/realtime/realtimecomponent) - Creating a RealtimeComponent subclass (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.ai7mo ago
<@276154194606424064> kapa.ai is still learning and improving, please let us know how it did by reacting below
Voltaia
VoltaiaOP7mo ago
@Normcore Assistant how can I tell if a RealtimeDictionary model has been updated?
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The RealtimeDictionary class in Normcore provides several events that you can subscribe to in order to know when the dictionary has been updated. These events are: 1. modelAdded: This event fires when a model is added to the dictionary, either locally or remotely. 2. modelReplaced: This event fires when a model in the dictionary is replaced, either locally or remotely. A model is considered replaced if a new model is added that overwrites an existing model under the same key. 3. modelRemoved: This event fires when a model is removed from the dictionary, either locally or remotely. Here's an example of how you might subscribe to these events:
RealtimeDictionary<MyModel> myDictionary = ... // Get your RealtimeDictionary

myDictionary.modelAdded += ModelAdded;
myDictionary.modelReplaced += ModelReplaced;
myDictionary.modelRemoved += ModelRemoved;

void ModelAdded(string key, MyModel model) {
// Handle model added
}

void ModelReplaced(string key, MyModel model) {
// Handle model replaced
}

void ModelRemoved(string key) {
// Handle model removed
}
RealtimeDictionary<MyModel> myDictionary = ... // Get your RealtimeDictionary

myDictionary.modelAdded += ModelAdded;
myDictionary.modelReplaced += ModelReplaced;
myDictionary.modelRemoved += ModelRemoved;

void ModelAdded(string key, MyModel model) {
// Handle model added
}

void ModelReplaced(string key, MyModel model) {
// Handle model replaced
}

void ModelRemoved(string key) {
// Handle model removed
}
In this example, MyModel would be the type of model stored in your RealtimeDictionary. Remember to unsubscribe from these events when you're done with them to prevent memory leaks. Source: RealtimeDictionary (https://normcore.io/documentation/reference/classes/Normal.Realtime.Serialization.RealtimeDictionary%601) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@276154194606424064> kapa.ai is still learning and improving, please let us know how it did by reacting below
Voltaia
VoltaiaOP7mo ago
@Normcore Assistant So, I can not update a model in a RealtimeDictionary? In order to "update" it I must replace it?
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, that's correct. In the context of a RealtimeDictionary in Normcore, an "update" to a model is effectively a replacement. When you want to update a model in the dictionary, you add a new model with the same key. This overwrites the existing model under that key, which is considered a "replacement". The RealtimeDictionary class provides a modelReplaced event that fires when a model is replaced in this way. This event can be used to handle updates to models in the dictionary. Here's an example of how you might "update" a model in a RealtimeDictionary:
RealtimeDictionary<MyModel> myDictionary = ... // Get your RealtimeDictionary
uint key = ... // The key of the model you want to update
MyModel newModel = ... // The new model

// "Update" the model by replacing it
myDictionary.Add(key, newModel);
RealtimeDictionary<MyModel> myDictionary = ... // Get your RealtimeDictionary
uint key = ... // The key of the model you want to update
MyModel newModel = ... // The new model

// "Update" the model by replacing it
myDictionary.Add(key, newModel);
In this example, MyModel would be the type of model stored in your RealtimeDictionary. Source: RealtimeDictionary (https://normcore.io/documentation/reference/classes/Normal.Realtime.Serialization.RealtimeDictionary%601) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
Voltaia
VoltaiaOP7mo ago
@Normcore Assistant so what happens when I access the RealtimeDictionary like this?
model.customDictionary[itemIndex].customBoolean = true;
model.customDictionary[itemIndex].customBoolean = true;
Will customBoolean be synced?
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, the customBoolean will be synced. When you access a RealtimeModel stored in a RealtimeDictionary and modify one of its properties, Normcore will automatically sync the change across all clients. Here's what happens when you run the line of code you provided:
model.customDictionary[itemIndex].customBoolean = true;
model.customDictionary[itemIndex].customBoolean = true;
1. You access the RealtimeModel at itemIndex in customDictionary. 2. You set the customBoolean property of that model to true. 3. Normcore automatically syncs the change to customBoolean across all clients. Remember, Normcore automatically handles syncing model data across all clients. All you need to do is keep the scene and the model in sync. Sources: - RealtimeDictionary (https://normcore.io/documentation/reference/classes/Normal.Realtime.Serialization.RealtimeDictionary%601) - RealtimeModel (https://normcore.io/documentation/room/realtimemodel) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@276154194606424064> kapa.ai is still learning and improving, please let us know how it did by reacting below
Voltaia
VoltaiaOP7mo ago
@Normcore Assistant but there exists no event to check that it has been synced?
kapa.ai
kapa.ai7mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Correct, the RealtimeDictionary class does not provide a specific event that fires when a property of a model within the dictionary is updated. The events provided by RealtimeDictionary (modelAdded, modelReplaced, modelRemoved) are related to the addition, replacement, or removal of models in the dictionary, not changes to the properties of those models. However, if you want to know when a property of a model has been updated, you can add a change event to the model itself. This can be done by setting the changeEvent argument to true when defining the property in the model. When this is set to true, a C# event is added to the model that will fire when the property is changed, either locally or remotely. Here's an example of how you might define a property with a change event in a RealtimeModel:
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true)]
private bool _customBoolean;
}
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true)]
private bool _customBoolean;
}
In this example, _customBoolean is a property of MyModel that has a change event. When _customBoolean is changed, the change event will fire. Sources: - RealtimeDictionary (https://normcore.io/documentation/reference/classes/Normal.Realtime.Serialization.RealtimeDictionary%601) - Change Event (https://normcore.io/documentation/realtime/synchronizing-custom-data#change-event) - RealtimeModel / RealtimeProperty attributes (https://normcore.io/documentation/room/realtimemodel#change-event) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai7mo ago
<@276154194606424064> kapa.ai is still learning and improving, please let us know how it did by reacting below
Voltaia
VoltaiaOP7mo ago
Aghhh