How to replicate a ball's physics on each client

I was wondering how certain games seem to achieve a super smooth ball, one in particular is this game:

I am convinced that this game does NOT use network ownership, rather, I believe the server handles the physics entirely, and the physics are replicated on each client, if so, how did they get the physics to be applied so smoothly?

I am trying to look for any alternatives to just using network ownership as that can cause lag when the network ownership gets switched between players

2 Likes

The server has an invisible ball. The client has a ball. The server sends the position, and velocity of the ball to the client, the client then applies that to their ball. Since the client is handling their own ball, and the physics for it, it will appear smooth. You will need to update the client ball’s position every .25 seconds or so to make sure it stays in the right place.

4 Likes

Can you explain more how I can get the velocity to be applied on the client while still making it update to the server ball’s position??

I’m still working on that myself. My current solution is just to teleport it to the server ball’s position+ any ping offset, and then let physics handle it until the next update time. Generally it’s less than .1 studs off, which isn’t really noticeable, but in some cases where the ball is moving faster, it may have some trouble. I’m looking into an other option however. Instead of directly teleporting the ball to where it needs to be, I would predict where the server ball will be, and then try to tilt the ball back that direction. That way, It would be smooth, and if the ball gets off track, it would slowly readjust itself. If you try this option, let me know if it works out for you!

I figured out a solution for this.

Server:

I fire the ball back to the client and optimizing it when I want the ball to be most smooth.

	while currentBall and currentBall.body.CFrame.Position.Y >= (lastBallCFrame.Position.Y - 6) do

			replicationRemoteEvents:FindFirstChild("ReplicateBallRemoteEvent"):FireClient(player, currentBall, currentBall.body.CFrame, replicationDuration);
			
			if currentBall.body.CFrame.Position.Y >= (lastBallCFrame.Position.Y + 1) then
				replicationDuration = .25

				task.wait(.05);
			else
				replicationDuration = .35

				task.wait(.2);
			end
		end

On the client I just tween the ball to its directed position. No velocity required.

replicationRemoteEvents:FindFirstChild("ReplicateBallRemoteEvent").OnClientEvent:Connect(function(ballModel: Model, ballCFrame: CFrame, replicationDuration: number)
	ballModel.body.Anchored = true
	tweenService:Create(ballModel.body, TweenInfo.new(replicationDuration, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {CFrame = ballCFrame}):Play();
	
1 Like

Another solution is using roblox physics constraints like Linear Velocity to move the ball instead of animation physics which is being used for my solution.

1 Like

Do you have a place showcasing this “solution”? If so, would you mind sharing a simple template place for it?

The main problem is that when I want to apply a force to the ball, then that force will take like 0.2 seconds to actually apply, and I know it’s a small delay, but when I just use network ownership, that delay is nonexistent

The only alternative i can think of is using RemoteEvent:FireAllClients() or something along these lines with parameters that update the ball.
Like @PiercedMissile said, you can have an invisivle ball too, this often works for all projectiles systems, for example, fastcast. Fastcast has a invisivls raycast but you can make a projectile on client to make it smooth