This article outlines some internal functionality of Touched and TouchEnded event replication in the distributed physics engine, with the goal of helping you understand how to approach touch event scenarios in your Roblox experiences.
To get the most out of this material, you should be an advanced developer who’s familiar with network replication delay.
Example Scenarios
Server/Client Async Scenario
In one example scenario, a server script has Touched and TouchEnded event listeners for a PartB, and the server owns that part. When PartB touches/un-touches another part PartA on the server (both with CanTouch set to true), an event is triggered and replicates to other clients. Note that if PartA and PartB have touched/un-touched on one client, it might not be the case on the server or another client.
The following diagram illustrates this scenario across time (t):
t = 1 | |
---|---|
Client1 | PartA moves further away from PartB. |
Server | PartB moves closer to PartA and touches it, since the movement of PartA on Client1 has not yet broadcast to Server. A Touched event is triggered here. |
t = 2 | |
---|---|
Client1 | Receives the Touched event broadcast from Server at t=1, as well as the CFrame update of PartB. However, the received event appears inaccurate since PartA previously moved on this client at t=1 and does not overlap PartB. |
Server | CFrame of PartA is received from Client1, meaning PartA and PartB move apart and trigger a TouchEnded event. |
Client2 | Receives the Touched event broadcast from Server at t=1, as well as the CFrame update of PartB. On this client, the event appears accurate since Server has not yet replicated the new non-touching CFrame of PartA. |
t = 3 | |
---|---|
Client1 | Receives the TouchEnded event broadcast from Server at t=2, although this event appears inaccurate since PartA and PartB never touched on this client across t=0 to t=3. |
Client2 | Receives the TouchEnded event broadcast from Server at t=2. On this client, the event appears accurate since Server has replicated the new non-touching position of PartA (note that PartA and PartB were touching at t=2 on this client). |
Client Event Dispatching
If PartA is owned by one client and PartB is owned by another client, you might get the same event twice everywhere, because each client triggers its event and broadcasts it to the server which then rebroadcasts it to the other client, as long as both parts exist on the receiving client. In our engine, we try our best to merge this “same” event, however, it’s difficult to identify and merge all of the same events.
The following diagram illustrates this scenario across time (t):
t = 1 | |
---|---|
Client2 PartB moves closer to PartA and touches it, triggering a Touched event which is broadcast to Server. The CFrame change of PartB is also replicated to Server. |
t = 2 | |
---|---|
Server The Touched event and the CFrame update for PartB from Client2 at t=1 is received and then rebroadcast to Client1. |
t = 3 | |
---|---|
Client1 Receives the Touched event and CFrame update for PartB broadcast from Server at t=2. A second Touched event is triggered on PartA which is broadcast to Server. |
t = 4 | |
---|---|
Server The Touched event for PartA from Client1 at t=3 is received and then rebroadcast to Client2. |
t = 5 | |
---|---|
Client2 Receives the Touched event for PartA broadcast from Server at t=4. |
Guidance
-
If the callback function needs to be executed immediately, make sure the local client owns at least one of the two parts (see Network Ownership) so the event triggers locally.
-
You can always expect to receive a Touched or TouchEnded event if it was ever triggered on remote server/clients, but anticipate a delay. This guarantees eventual consistency.
-
For security purposes, use the server to validate if a Touched or TouchEnded event is valid or not if the event was triggered on a client. For example, check the distance between the two parts to make sure they are close enough to trigger the touch event.