Trying to do locally rendered ship models

Hey devfourm, I am currently making a physics-based ship system where the actual ship models are individually run on each client.


  • A “ShipRoot” is created by the server and Network Ownership given to the player that spawned it (Captain), the Captain controls the physics of the boat.

  • There is no shipmodel on the server, only the ShipRoot.

  • :FireAllClients() is fired by a RemoteEvent when the ship is spawned by the server, which tells every client to locally render the ship models and start positioning them.

I have tried a variety of solutions: Alignposition, BodyPosition, BodyGyro, AlignOrientation, Welds, Constraints, Velocities, but all of these usually had one or multiple of the following issues:

  1. Client attaches the local render to the ShipRoot, but begins ignoring the network ownership and the position of the ShipRoot (Welds and Motor6D).

  2. Player doesn’t move with the local rendered ship model and slides off.

  3. Player DOES move with the local ship model, but it looks very unstable and jittery. (Align Position)

**Example of issue 3: **
Captain perspective: (You can see its very smooth)

Other client perspective: (you can see its jittery)

I have looked through devfourm and tried all kinds of stuff, any suggestions or methods on how I can achieve this?

I’m not sure if it’s similar to optimizing Pet Games by rendering them by the client, but I’ll tell you how to do that and hopefully it works for you.

Instead of having the server have to communicate the information of the ship, the positioning, etc every second. You could put the Root of the ship in a certain Folder and have information about the ship (like the model and stuff, anything necessary to sync it to your client) and have the ship model be synced on the client to the Root, and not have to go through a RemoteEvent.

Instead of using a for loop. You will instead use a ChildAdded in the Folder where shiproots are called. You can then assign it to a RenderStepped or Heartbeat. Whatever is more conveinient for you.

local ships = game.Workspace.Ships

	local ShipConnection = game:GetService("RunService").RenderStepped:Connect(function()
		-- Do all your syncing and stuff
	-- Once our ship is being removed or Destroyed. We can end the RenderStepped Thread saving us some memory for new ships.

You could even stick some Remotes in there to FireAllClients to sync like Animations, a Cannon shooting, or simply just a door being opened.

Have fun.

The server doesn’t communicate the info, it just creates the original ShipRoot so that all the clients can see it. Each client just gets the position from the ShipRoot and uses that to align the ship

I only use a remote to FireAllClients() when the ship is originally created

this is the shiproot without local rendering

The only thing I can think of that may HELP with the jittering (but possibly not completely stop it) is to set the players Position on the Client, then send a Unreliable RemoteEvent to the server to then set their position one more time.

This will sync the Player to the Servers tick, instead of going though Client Tick. Which will be based completely on Frames Per Second vs the Strong server, that usually stays around 60 Frames per second.

Even though you’re using NetworkOwnership. All network ownership does is have the server not calculate the Physics, but it still passes back through the server to all the clients. So almost everything runs though the server.

thanks for the feedback, I kind of messed a bit around with unreliableevents for this but didn’t really fully commit to it yet, I’ll probably do a mix between the UnreliableRemoteEvents and networkownership to achieve the goal

hi again, I did some more testing and found that the ship models were actually perfectly synced across all clients(to my delight), the only issue being the client both lagging behind to other players as well as its unstable reacting with the ship. Can you elaborate a bit more on positioning the player?

Alright. Sorry for my response time.

Here’s a video of me explaining it.

Since I may not make sense. In turn, Sync player on the client then send the final position data through an unreliable RemoteEvent, which will then FireAllClients through the same event and set the position on every other client of where you’re supposed to be. I haven’t tried it yet, but I think it would work fine.

If not. I have another idea.
Calculate yourself and other players at the same time. Since it’s all on the client, only you will see it. This could remove a lot of the delay of having to wait for another players client to sync it.

again, thanks for the feedback and even recording making a video explaining in depth, I will definitely test this out soon (right now lol).

First of all, @Laqotaa made an excellent explanation on this; I’m just adding on.

I’m not the expert on player physics, but this “jittering” effect seems to be common among Roblox games with moving platforms and is due to lag between one client and another.

For humanoids, Roblox will use the client’s position as the source of truth and render it to other players. However, the time required to refresh this will depend on the latency of every player. The reason why the ship is able to replicate perfectly is because the server is the source of truth of the ship’s position. The server directly controls the ship through your physics controllers, so it has the final word on it’s position. Therefore, everyone can see the ship perfectly.

Player Replication

Client → Server → All Clients
If a player is lagging, the server will not be able to sync their position in real time to the other players, resulting in jittering.

Ship Replication

Server → All Clients
The server has sole control of the ship, and all calculations and changes to position are replicated immediately.

A solution to this would be to do the same thing with your client’s humanoids (server authority). Imagine if, just like the ship, every player’s position was handled by the server. This would ensure that every client would be updated on time and that physics calculations remain consistent and “jitter free.”

A good example of this is Chickynoid, which you can find below.

I found a solution, Ill put it here for anyone that sees this:
I went back to welding the local model to the ShipRoot, except I manually set the assembly models PrimaryPart to the ShipRoot after figuring out that when I parented the local model under the ShipRoot model, the primarypart changed

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.