Niv
Niv2w ago

What happens when state changes very close to (or same frame) when the object is destroyed?

Are we guaranteed to get the latest known state to update before the object is destroyed? Or is it possible the object will get destroyed without assuring remote clients "see" the last state of the object before it is destroyed?
6 Replies
kapa.ai
kapa.ai2w ago
Hi @Niv. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To answer this question accurately, we need to consider how Normcore handles state synchronization and object destruction. Based on the provided knowledge sources, there isn't specific information addressing this exact scenario. However, we can infer some relevant details from the available information. Normcore uses a datastore to synchronize state between clients. As mentioned in the Client Architecture documentation: "All state is synchronized using the room's datastore. If you need to move an object in the world, you change its position in the datastore. The datastore will automatically detect any changes and notify all clients connected to the room so they can update their world to match." Additionally, the documentation states: "To conserve on bandwidth, once the server has sent the initial datastore snapshot, it will only send delta updates for the remainder of the session." This suggests that state changes are not immediately synchronized, but rather sent as delta updates periodically. Regarding object destruction, the Common Questions documentation mentions: "If you're not using RealtimeSet directly in your project, this can happen if multiple clients call Realtime.Destroy() on the same object at the same time. In order to prevent this, we generally recommend having the client that owns the object destroy it: if (realtimeView.isOwnedLocally) Realtime.Destroy(gameObject);." Given this information, we cannot guarantee that the latest known state will always be updated before the object is destroyed, especially if the state change and destruction occur very close together or in the same frame. There's a possibility that the object could be destroyed before the final state update is synchronized to all clients. To ensure that remote clients see the last state of the object before it's destroyed, you might need to implement a custom solution. For example, you could: 1. Update the state 2. Wait for a short period or until the next network frame 3. Then destroy the object However, it's important to note that this approach is not explicitly documented in the provided knowledge sources and would require careful implementation and testing. For the most accurate and up-to-date information on this specific scenario, it would be best to consult with the Normcore support team or check for any newer documentation that might address this particular use case. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@269927864265211906> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mechabit
Mechabit2w ago
the only way to ensure a message is received by the server is to use the StringKeyDictionary collection. It's the only model that is transactional in your case you update the state with string key dictionary and wait for the didInsertModelForKey event then you can safely do other stuff
maxweisel
maxweisel2w ago
If you make a change to a reliable property, it will go out in the same packet as the destroy event. However, when it's received, it may be deserialized out of order, so GameObject.Destroy() may run before the models are updated (although I believe OnDestroy() isn't called until later in the frame) unreliable properties are sent on a different channel and can arrive out of order with reliable updates made at the same time (Destroy is a reliable update). And if the packet arrives late, and the object has been destroyed, the updates will be discarded In general, I wouldn't recommend trying to send data and destroy at the same time though. Typically the best model for this is to send a reliable state update that tells clients "Here's the final state, and you should hide this object from the scene" if the data is still important. Followed by a clean-up Destroy() call later on when you're absolutely sure accessing data on the object is no longer needed as @Mechabit mentioned, StringKeyDictionary is also a great way to perform atomic updates and to receive confirmation that the server received them.
Niv
NivOP2w ago
Thanks Max that clears it up. While you mentioned reliable vs. unreliable - are unreliable generally quicker to arrive (assuming no packet loss)? or do they use a similar pipe?
maxweisel
maxweisel2w ago
same round trip time. it’s all over UDP, the only difference is reliable messages are sent repeatedly until the destination confirms receipt, and for both channels we guarantee packets will arrive in the same order they’re sent this does mean if a reliable packet is dropped, reliable packets sent after it will stall until it’s received, which can increase latency in that case. However with datastore updates it’s rare to see a stall long enough to affect the next datastore update.

Did you find this page helpful?