Art3m1s
Art3m1s3mo ago

No definition when trying to access DidChange callback

I have this error message: Assets/Scripts/GameState/GameStateSync.cs(17,27): error CS1061: 'GameStateModel' does not contain a definition for 'playerstatesDidChange' and no accessible extension method 'playerstatesDidChange' accepting a first argument of type 'GameStateModel' could be found (are you missing a using directive or an assembly reference?) This is how I defined playerstates in the model: [RealtimeProperty(1, true, true)] private RealtimeDictionary<PlayerStateModel> _playerstates;
Solution:
---------------------- The error message you're seeing is indicating that there's no playerstatesDidChange event in your GameStateModel. This event is typically generated when you set the last argument of the RealtimeProperty attribute to true, which you have done. However, it seems like the event is not being generated for your RealtimeDictionary. The issue might be related to the use of RealtimeDictionary with the RealtimeProperty attribute. In the provided knowledge sources, the examples of RealtimeProperty usage are with primitive types like Color and string, not with RealtimeDictionary. ...
Jump to solution
11 Replies
kapa.ai
kapa.ai3mo ago
Hi @Art3m1s. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Solution
kapa.ai
kapa.ai3mo ago
---------------------- The error message you're seeing is indicating that there's no playerstatesDidChange event in your GameStateModel. This event is typically generated when you set the last argument of the RealtimeProperty attribute to true, which you have done. However, it seems like the event is not being generated for your RealtimeDictionary. The issue might be related to the use of RealtimeDictionary with the RealtimeProperty attribute. In the provided knowledge sources, the examples of RealtimeProperty usage are with primitive types like Color and string, not with RealtimeDictionary. Here is an example from the knowledge sources:
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true )] private string _name;
[RealtimeProperty(2, true )] private Color _avatarPrimaryColor;
[RealtimeProperty(3, true )] private Color _avatarAlternateColor;
[RealtimeProperty(4, false)] private Vector3 _movementVelocity;
}
[RealtimeModel]
public partial class MyModel {
[RealtimeProperty(1, true )] private string _name;
[RealtimeProperty(2, true )] private Color _avatarPrimaryColor;
[RealtimeProperty(3, true )] private Color _avatarAlternateColor;
[RealtimeProperty(4, false)] private Vector3 _movementVelocity;
}
In this example, RealtimeProperty is used with string, Color, and Vector3 types. It's possible that RealtimeDictionary might not support the automatic generation of change events. I would recommend checking the Normcore documentation or reaching out to their support for more information on this. If you're using Unity 2021 or newer, Normcore will automatically generate the remaining code needed to use your model. If you're using an older version of Unity, you will need to manually compile the model. Make sure your Unity project has no compile errors. If Unity is unable to compile this class, it will be unable to detect the changes you’ve made to your model (source (https://normcore.io/documentation/realtime/synchronizing-custom-data#generating-model-code-in-unity-2019/2020​)).
kapa.ai
kapa.ai3mo ago
If you're new to RealtimeModel, you might find the Synchronizing custom data (https://normcore.io/documentation/realtime/synchronizing-custom-data) guide helpful. It provides an excellent overview of how to use a RealtimeModel in practice (source (https://normcore.io/documentation/room/realtimemodel)). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@185544015314288641> kapa.ai is still learning and improving, please let us know how it did by reacting below
Art3m1s
Art3m1s3mo ago
@Normcore Assistant how do I define my own callback for the RealtimeDictionary then
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- To define your own callbacks for a RealtimeDictionary, you can subscribe to the events provided by the RealtimeDictionary class. These events are modelAdded, modelReplaced, and modelRemoved. They fire when a model is added, replaced, or removed respectively, either locally or remotely. Here's an example of how you can subscribe to these events:
public class MyComponent : RealtimeComponent<MyModel> {
protected override void OnRealtimeModelReplaced(MyModel previousModel, MyModel currentModel) {
if (previousModel != null) {
// Unsubscribe from events on the old model.
previousModel.playerstates.modelAdded -= PlayerStateAdded;
previousModel.playerstates.modelReplaced -= PlayerStateReplaced;
previousModel.playerstates.modelRemoved -= PlayerStateRemoved;
}
if (currentModel != null) {
// Subscribe to events on the new model.
currentModel.playerstates.modelAdded += PlayerStateAdded;
currentModel.playerstates.modelReplaced += PlayerStateReplaced;
currentModel.playerstates.modelRemoved += PlayerStateRemoved;
}
}

private void PlayerStateAdded(ModelAddedEventArgs<PlayerStateModel> args) {
// Handle the player state added event.
}

private void PlayerStateReplaced(ModelReplacedEventArgs<PlayerStateModel> args) {
// Handle the player state replaced event.
}

private void PlayerStateRemoved(ModelRemovedEventArgs<PlayerStateModel> args) {
// Handle the player state removed event.
}
}
public class MyComponent : RealtimeComponent<MyModel> {
protected override void OnRealtimeModelReplaced(MyModel previousModel, MyModel currentModel) {
if (previousModel != null) {
// Unsubscribe from events on the old model.
previousModel.playerstates.modelAdded -= PlayerStateAdded;
previousModel.playerstates.modelReplaced -= PlayerStateReplaced;
previousModel.playerstates.modelRemoved -= PlayerStateRemoved;
}
if (currentModel != null) {
// Subscribe to events on the new model.
currentModel.playerstates.modelAdded += PlayerStateAdded;
currentModel.playerstates.modelReplaced += PlayerStateReplaced;
currentModel.playerstates.modelRemoved += PlayerStateRemoved;
}
}

private void PlayerStateAdded(ModelAddedEventArgs<PlayerStateModel> args) {
// Handle the player state added event.
}

private void PlayerStateReplaced(ModelReplacedEventArgs<PlayerStateModel> args) {
// Handle the player state replaced event.
}

private void PlayerStateRemoved(ModelRemovedEventArgs<PlayerStateModel> args) {
// Handle the player state removed event.
}
}
In this example, PlayerStateAdded, PlayerStateReplaced, and PlayerStateRemoved are methods that you define to handle the respective events. When a player state is added, replaced, or removed, the corresponding method will be called. You can find more information about the RealtimeDictionary class and its events in the Normcore documentation (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.ai3mo ago
<@185544015314288641> kapa.ai is still learning and improving, please let us know how it did by reacting below
Art3m1s
Art3m1s3mo ago
@Normcore Assistant lets say i hae a function that updates a RealtimeModel how do I just have that run by the server, not by all clients?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- To have a function run only on the server and not on all clients, you can use the RealtimeView.isOwnedByServer property to check if the current instance is owned by the server. If it is, you can then execute your function. Here's an example:
public class MyComponent : RealtimeComponent<MyModel> {
private void Update() {
if (realtimeView.isOwnedByServer) {
// This code will only run on the server.
UpdateMyModel();
}
}

private void UpdateMyModel() {
// Your function that updates the model.
}
}
public class MyComponent : RealtimeComponent<MyModel> {
private void Update() {
if (realtimeView.isOwnedByServer) {
// This code will only run on the server.
UpdateMyModel();
}
}

private void UpdateMyModel() {
// Your function that updates the model.
}
}
In this example, UpdateMyModel is your function that updates the model. It will only be called if the current instance is owned by the server. Please note that this approach assumes that you have a RealtimeView component attached to the same game object as your custom component. The RealtimeView component is used to manage the ownership and synchronization of game objects in Normcore. For more information about ownership in Normcore, you can refer to the Ownership and Lifetime Flags (https://normcore.io/documentation/room/ownership-and-lifetime-flags) section of the Normcore documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@185544015314288641> kapa.ai is still learning and improving, please let us know how it did by reacting below
Mechabit
Mechabit3mo ago
normcore servers don't run any code. you can make code run only on one client that can act kinda like a host