Network Ownership

The Roblox physics engine assigns network ownership of physically simulated BaseParts to either a client or server to divide the work of calculating physics. The server or client that calculates a part's physics is called its owner. Experiences with complex physics interactions may require you to manage network ownership directly.

BasePart Ownership

By default, the server has ownership of any part. The server always owns anchored parts, and you cannot manually change their ownership. If a client's character is near an unanchored part, then the ownership of that part transfers to the character's client.

Clients experience more responsive physics interactions with parts that they own, since there's no latency from communication with the server. Network ownership also improves server performance because physics computations can be split up among individual clients, allowing the server to prioritize other tasks.

Assembly Ownership

If a physics-based mechanism has no anchored parts, setting the ownership of an assembly within that mechanism sets the ownership of every part in the mechanism. If you anchor the assembly, the ownership remains on the other assemblies if the rest of the mechanism isn't anchored. Unanchoring the assembly returns the previously set ownership.

If an assembly is the only thing in the mechanism, anchoring the assembly resets the network ownership on all of the assembly's parts to **Auto**. If you unanchor the assembly, ownership ignores previous settings and remains Auto.

Constraints between two assemblies with different network ownerships aren't stable. In cases where two clients own two different assemblies joined by a constraint, you should ensure that ownership transfers to a single client.

Setting Ownership

When a part collides with another object, Roblox automatically assigns BasePart network ownership to the client closest to it. However, this doesn't always produce desirable behavior. In cases where you need to take direct control of ownership, you can set it directly by calling SetNetworkOwner().

SetNetworkOwner() and GetNetworkOwner() can only be called by the server. The server always owns anchored parts, so you can only change the ownership of unanchored parts.

Vehicles Example

Consider a vehicle that has a VehicleSeat object for the driver and a Seat object for a passenger, with both included in the vehicle assembly. With the default ownership rules, if a player sits in the Seat (passenger) and then another player jumps into the VehicleSeat (driver), the passenger gets physical ownership of the whole vehicle. The driver will have to wait several network cycles before their input is recognized and the vehicle will feel less responsive.

The following script fixes this by manually setting network ownership of the car to the driver. In the following example, the VehicleSeat sets VehicleSeat.Occupant to the Humanoid sitting on it, so the script listens for the seat's Changed event to catch when a player sits in the seat. When the driver leaves the seat, the vehicle's network ownership can be set back to automatic with SetNetworkOwnershipAuto().

-- Script inside of VehicleSeat
local VehicleSeat = script.Parent
if prop == "Occupant" then
local humanoid = VehicleSeat.Occupant
if humanoid then
-- Get the player from the character
local player = game:GetService("Players"):GetPlayerFromCharacter(humanoid.Parent)
if player then
-- Reset ownership when seat is unoccupied

Projectiles Example

Imagine a player is throwing an object at another player. As the object travels through the air, it becomes far from the thrower and ownership switches to the server. Once the object gets close enough to the target player, its ownership switches to the target player. Even with a good network connection, there may be visible lag in the movement of the object when the owner switches. The following code samples set ownership of the projectile to the server so that it doesn't change in motion, preventing visible jumps in movement.

For example, the following LocalScript listens for keyboard input from the player and fires a RemoteEvent to the server to both create the projectile and set its ownership.

-- LocalScript (client)
game:GetService("ContextActionService"):BindAction("Throw", function(actionName, state, object)
if state == Enum.UserInputState.Begin then
end, false, "h")

The server Script creates a new projectile and sets its ownership to nil, ensuring its ownership does not change from the server as it travels.

-- Script (server)
-- Get the direction player is facing
local direction = player.Character.Torso.CFrame.lookVector * 5
-- Create projectile and give it velocity in the direction player is facing
local projectile = game.ServerStorage.Projectile:Clone()
projectile.Parent = game.Workspace
projectile.PrimaryPart.CFrame = + direction +,2,0))
projectile.PrimaryPart.Velocity = direction * 40 +,40,0)
-- Set the server as the owner of the projectile

Visualizing Ownership

You may find it useful to enable the studio debugging visualization in order to better understand how network ownership changes while an experience runs. To enable ownership visualization:

  1. Click on File in the top left corner and select Studio Settings.
  2. Navigate to the Physics tab.
  3. Enable Are Owners Shown under the Display section.

Security Concerns

Roblox cannot verify physics calculations when a client has ownership over a BasePart. Clients can exploit this and send bad data to the server, such as teleporting the BasePart, making it go through walls or fly around. Ensure you validate any physics interactions reported by clients on the server.

Touched events are tied to network ownership, meaning the network owner can fully control when they fire. A client can fire Touched events on a part it owns and send it to the server, even if the server doesn't see it touch anything. For example, a client can make a sword deal damage to another player across the map by firing the event through script injections. It's important to check the validity of Touched events fired by clients.