cryptomax
cryptomax3mo ago

How is StopWatch Recipe updating other clients?

I dont see a didchange event in this model so how is this starting the stop watch on clients other than the one who started the stopwatch model? using Normal.Realtime; using Normal.Realtime.Serialization; [RealtimeModel] public partial class StopWatchModel { [RealtimeProperty(1, true)] private double _startTime; } /* ----- Begin Normal Autogenerated Code ----- */ public partial class StopWatchModel : RealtimeModel { public double startTime { get { return _startTimeProperty.value; } set { if (_startTimeProperty.value == value) return; _startTimeProperty.value = value; InvalidateReliableLength(); } }
public enum PropertyID : uint { StartTime = 1, }
#region Properties
private ReliableProperty<double> _startTimeProperty;
#endregion
public StopWatchModel() : base(null) { _startTimeProperty = new ReliableProperty<double>(1, _startTime); }
protected override void OnParentReplaced(RealtimeModel previousParent, RealtimeModel currentParent) { _startTimeProperty.UnsubscribeCallback(); }
protected override int WriteLength(StreamContext context) { var length = 0; length += _startTimeProperty.WriteLength(context); return length; }
protected override void Write(WriteStream stream, StreamContext context) { var writes = false; writes |= _startTimeProperty.Write(stream, context); if (writes) InvalidateContextLength(context); }
protected override void Read(ReadStream stream, StreamContext context) { var anyPropertiesChanged = false; while (stream.ReadNextPropertyID(out uint propertyID)) { var changed = false; switch (propertyID) { case (uint) PropertyID.StartTime: { changed = _startTimeProperty.Read(stream, context); break; } default: { stream.SkipProperty(); break; } } anyPropertiesChanged |= changed; } if (anyPropertiesChanged) { UpdateBackingFields(); } }
private void UpdateBackingFields() { _startTime = startTime; }
}
Solution:
you don't need an extra int, just add the udpate event parameter to this model
Jump to solution
12 Replies
kapa.ai
kapa.ai3mo ago
Hi @cryptomax. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The StopwatchModel in the Normcore VR platform uses a property _startTime to hold the room time when the stopwatch was started. This property is marked with the [RealtimeProperty] attribute, which means it is automatically synchronized across all clients connected to the same room. When the StartStopwatch() method is called, it sets the _startTime to the current room time. This change is then propagated to all other clients due to the [RealtimeProperty] attribute. Here is the relevant code:
[RealtimeModel]
public class StopwatchModel {
[RealtimeProperty(1, true)] private double _startTime;
}

public class Stopwatch : RealtimeComponent<StopwatchModel> {
public void StartStopwatch() {
model.startTime = realtime.room.time;
}
}
[RealtimeModel]
public class StopwatchModel {
[RealtimeProperty(1, true)] private double _startTime;
}

public class Stopwatch : RealtimeComponent<StopwatchModel> {
public void StartStopwatch() {
model.startTime = realtime.room.time;
}
}
In this case, there is no need for a didChange event because the Normcore platform handles the synchronization of [RealtimeProperty] attributes automatically. When _startTime is updated, the new value is automatically sent to all other clients. You can find more details in the Normcore Documentation (https://normcore.io/documentation/guides/recipes/timers-and-synchronized-playback). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@401986039964631060> kapa.ai is still learning and improving, please let us know how it did by reacting below
cryptomax
cryptomax3mo ago
@Normcore Assistant so you can make realtime properties that will automatically sync with all clients whenever they change? How do you catch the changes though?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can create Realtime properties in Normcore that will automatically synchronize with all clients whenever they change. This is done by marking the property with the [RealtimeProperty] attribute in your model class. Here is an example:
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true )] private string _name;
}
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true )] private string _name;
}
In this example, _name is a Realtime property that will be synchronized across all clients. To catch the changes, you can subscribe to the didChange event of the property. This event is fired whenever the property changes. You can then define a method that will be called when this event is fired. Here is an example:
protected override void OnRealtimeModelReplaced(MyModel previousModel, MyModel currentModel) {
if (previousModel != null) {
// Unregister from events
previousModel.nameDidChange -= NameDidChange;
}
if (currentModel != null) {
// Register for events
currentModel.nameDidChange += NameDidChange;
}
}

private void NameDidChange(MyModel model, string value) {
// The name property has changed, do something with the new value
}
protected override void OnRealtimeModelReplaced(MyModel previousModel, MyModel currentModel) {
if (previousModel != null) {
// Unregister from events
previousModel.nameDidChange -= NameDidChange;
}
if (currentModel != null) {
// Register for events
currentModel.nameDidChange += NameDidChange;
}
}

private void NameDidChange(MyModel model, string value) {
// The name property has changed, do something with the new value
}
In this example, NameDidChange is a method that will be called whenever the name property changes. You can put any code you want in this method to respond to the change. You can find more details in the Normcore 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.ai3mo ago
<@401986039964631060> kapa.ai is still learning and improving, please let us know how it did by reacting below
cryptomax
cryptomax3mo ago
I think I just got exceptionally confused....XD
Mechabit
Mechabit3mo ago
it updates on all clients but there's no event instead it polls time every frame
cryptomax
cryptomax3mo ago
so it is just updating constantly? but what would you use to initiate catching the fact that it started though?
Mechabit
Mechabit3mo ago
OnInspectorGUI() updates so long as you're looking at the inspector nothing, unless you want it to, then you add the event parameter in this example it only updates when you look at the inspector but importantly there's only 1 syncing variable, the start time, which makes this timing method better than say syncing a variable called current time less data being sent
cryptomax
cryptomax3mo ago
hmmm ok so you woudl sort of need a different way to know if it started like a different int and if that flips then you can start reading the timer because it will be running everywhere, or add an additional event to this
Solution
Mechabit
Mechabit3mo ago
you don't need an extra int, just add the udpate event parameter to this model
cryptomax
cryptomax3mo ago
thanks for explaining it a bit more