Avatar Physics Interactions
I'm building a VR game where you can push/hit someone and make them move (similar to Orion Drift ball where you can push someone and make them fly backwards).
What is ideal architecture for this? Thinking about using an RPC to send a rigidbody.AddForce event to your client when I intersect your avatar on my side. Considered having your local avatar have networked physics on them but not sure that makes sense from a multiplayer PVP perspective (eg the person hitting should be the source of truth).
So proposal is: I push your avatar on my client, trigger collider event happens, then it sends an RPC to your client which does the physics on your side. Your avatar maps to your rig, which just got pushed on your client, so everyone sees you move.
18 Replies
Hi @khoi. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
I'll help you understand the best approach for avatar physics interactions in NormalVR.
Your proposal to use RPCs for physics interactions isn't the recommended approach in Normcore. The documentation specifically warns against using RPC messages:
"Before we dive into this recipe, I'd like to warn you against using RPC messages... we believe this is a bad pattern. It puts the burden on you, the developer, to ensure that all state that is changed in response to an RPC message remains in sync across all clients." Recipe: RPC EventsInstead, Normcore has built-in solutions for networked physics that would be more appropriate for your use case. Recommended Architecture Normcore's
RealtimeTransform
component is designed specifically for networked physics interactions. Here's how you could structure your avatar physics:
1. Use RealtimeTransform with Rigidbody: Add a RealtimeTransform
component to your avatar with a Rigidbody component. This will automatically handle physics synchronization.
2. Ownership Management: Normcore uses an ownership model to determine which client is the source of truth for an object. For physics interactions:
"Normcore solves this by simulating physics locally when you interact with an object. For the local client, changes appear instant. If you toss a ball to another player, they're watching your simulation of the object while it's in flight. However, as soon as they interact with it, Normcore switches to their client's simulation so it appears to have zero-latency on their client as well." Why Normcore3. Automatic Collision Ownership: When physical objects collide, Normcore can automatically handle ownership transfer:
"When a rigidbody collides with another one, Normcore automatically claims ownership of the colliding rigidbody so the collision renders seamlessly on all clients." Why Normcore4. Player Avatar Ownership: For player avatars, you typically want to maintain ownership:
"We want to ensure that each player prefab can only be modified by the player that owns it. Rather than setting ownership of every component on the player, we can set ownership of the root RealtimeView, and the server will block all other clients from making modifications to any RealtimeView or RealtimeComponent model." Ownership and Lifetime FlagsFor player avatars specifically, you'll want to set "Maintain Ownership While Sleeping" on the RealtimeTransform:
"In this case, we want to retain ownership of the Player RealtimeTransform at all times. In order to do that, we'll want to set it to Maintain Ownership While Sleeping." Creating a Player ControllerImportant Considerations 1. Rigidbody Hierarchy: Be careful with parent-child relationships:
"Rigidbodies cannot have parent game objects unless the parent never moves." RealtimeTransform + Physics2. World Space Synchronization: For Rigidbodies, Normcore synchronizes in world space:
"Rather than synchronizing the localPosition and localRotation properties of the transform, it synchronizes the position and rotation properties of the Rigidbody, which are in world space instead of local space." RealtimeTransform + PhysicsBy leveraging Normcore's built-in physics synchronization rather than RPCs, you'll get more reliable results with less code and fewer potential desync issues. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
just so you know if you use Realtime Transform with this kind of message based send force there will be at least 1 second delay before the other play looks like they are moving due to the interpolation
i see!
how would you do it otherwise?
also we are having a bug with the RPC where we use model.FireEvent(xxx) and then the EventDidFire() is logging like 400 times? based on this recipe:
https://docs.normcore.io/guides/recipes/rpc-events
@kapa.ai is there a bug with RealtimeCallback?
Let me check the knowledge base for you again. One moment! :books:
----------------------
Based on the knowledge sources provided, there's no specific information about any bugs with RealtimeCallback in NormalVR. The documentation mentions RealtimeCallback as a way to get an event that fires once all updates have been applied to a model, but doesn't indicate any known bugs with this feature.
From the Room > Common Questions section:
"When model updates are applied, they're applied one at a time, and a change event fires for that value. However, it's possible the other values from that packet hadn't yet been applied. In order to get an event that fires once all updates have been applied to a model, use RealtimeCallback."However, the documentation doesn't provide further details about any specific issues or bugs with RealtimeCallback functionality. If you're experiencing a specific problem with RealtimeCallback, I'd recommend reaching out to the Normcore community or support team for more detailed assistance, as the knowledge sources don't contain enough information about potential bugs with this feature. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
are you on the latest version?
if you need RPC like behaviour you can just increment an int model and register for change events
i was in the easy sync alpha, now i dont know how to upgrade to latest normcore 2.15
😅
there is no upgrade button in my UPM

as for pushing another player there's no real good solution, you'll just have to work around the latency / interpolation
or you use deterministic physics or client prediction
yeah we are using the RPC recipe in the docs which says to increment a trigger so i think that is what you are talking about
try it without the realtime callback section and just use a basic model with change events
https://docs.normcore.io/realtime/synchronizing-custom-data#realtime-components but instead of color make it an int and instead of changing the material fire off a unity event
Synchronizing Custom Data | Normcore Documenation
In this guide, I’m going to walk you through how to synchronize custom data in your Unity application using custom realtime components.
How would I send the arguments across though? eg if I wanted to send pushStrength and pushVelocity?
i could sync those to the model too but then it wouldnt be guaranteed if all the data had come through yet
or the order
you can add those things to the model
but this method is only good for one off events
if you want lots of messages to fire at the same time you need to store them in a list
also everything in the model is sent at the same time
they won't arrive separately (and even if they are they are reconstructed in the background so it looks like it was)
RealtimeSet is good for sending lots of messages
properties will get deserialised in a random order though so to make sure you have everything ready you can wait till end of frame to read the contents