What would be the best way to apply a force to a ball without "stutters"?

Hi DevForum, I’m trying to achieve the best possible way to apply a force to a soccer ball (as in a kick) to make it move. I’ve tried :ApplyImpulse() and such, but it seems to have occasional “stutters”. Would there be any better way? Thanks again!

4 Likes

Stutters from ApplyImpulse and such are caused from ping issues. If you apply the force on the server, the ball will stutter for players with high ping. You need to apply the force from the client in order to remove any stuttering.

2 Likes

Adding to what was said above, you probably want to set the ball’s “Network Ownership” to the player who has kicked the ball, when they kick it, as the stutters you describe occur when the game is deciding if the part’s physics are to be determined either by the client or the server.

its as easy as

Basepart:SetNetworkOwnership(player)
2 Likes

Thank you both for your replies.

In addition to setting the impulse on the client, I’m a bit confused on the Network Ownership part, if you can elaborate that would be much appreciated.

I also feel that a BodyVelocity might do the job for movement, but I’m not sure. Any feedback?

Thanks again!

1 Like

BodyVelocity has been deprecated for a while, you can try setting a LinearVelocity to the “Line” mode, though (Keeping it set as the “Vector” mode prevents all physics from influencing it except for collisions that stop it)

1 Like

I see what you’re saying, thank you. Would a LinearVelocity be the best way to replicate this force? Or would there be better ways?

I’m sort of aiming for a way of applying forces to the ball displayed in this game

1 Like

Personally, LinearVelocity in Line mode would be the first thing I try for a soccer game, since it’s physics doing pretty much all the work and should be fast enough to not have much server lag.

2 Likes

Yes, you do have a point. I hyperlinked the game as an example, if you want to see what I mean in action, because it portrays my goal pretty clearly. I’ll give LinearVelocity a try, should it be on client or server?

2 Likes

I’ve never tried setting LinearVelocity to enabled on the client, I’m not sure what would happen, I assume it’d not work or only move the part locally because if it replicated that could be very easily exploitable.
Anyway considering your goal, because you want it to be the same position for all players, I’d say server.
As for the actual system, the LineDirection is straightforward, just set that to the direction the player is kicking in. Then for the LineVelocity, I’d set that to some max amount each time someone kicks it, maybe 25-30, then have a server script in the ball that’s always running and subtracts from the LineVelocity until it reaches 0.

This system should make the ball able to be influenced by outside physics while also being propelled forwards by the kick.

If this doesn’t work, you can go 1 step simpler and set the ball’s AssemblyLinearVelocity property to the kick direction multiplied by the speed you want it to go. This will automatically diminish over time based off friction and other physics stuff, and it’s a good alternative since you can adjust friction and density if you want it to go further.

1 Like

Network ownership allows the physics of an object to be calculated by that client. Roblox automatically switches the ownership from server to client when the player is close enough to an object, in order for the interaction to be smooth and responsive.

The “stutter” you describe could be because of the switching of network ownership from server to client and vice versa.
(i.e. players comes close to the ball causing switch to player ownership, and then player kicking the ball far from their range causing a switch back to server ownership)

this is a prime example that would cause stutters, and it becomes even worse if there are more players nearby.

To solve it you have to make it so the network ownership only changes based on the player touching/kicking the ball.

--//example script

local ball --your ball basepart

ball:SetNetworkOwnership() --start with the ownership set to server

ball.Touched:Connect(function(otherpart)
	--check if otherpart is a player
	local player = game.Players:GetPlayerFromCharacter(otherpart.Parent)
	if player == nil then return end
	--set ownership to player
	ball:SetNetworkOwnership(player)
end)
3 Likes

very informative response, you taught me something I don’t know and I’m not even the one who posted this :sob:

2 Likes

Angola velocity It’s not probably what you are looking for

What even is an applied Improves

Thank you and @Hqsuperlabgames very much for your replies, and I apologize for the late response.

Very informative, I appreciate the detailed explanation! Now to manipulate the velocities along with network ownership, as PieRat stated, I should still manipulate the LinearVelocity or such on the server, correct? Thank you again!

2 Likes

Just to weigh in again, now knowing what @arbitiu said, yes I think you should still use LinearVelocity, just also incorporating the NetworkOwnership system.

I say to use LinearVelocity over the ball’s AssemblyLinearVelocity property because you can control the speed at which it decelerates better, in my experience, and might even be able to make a slightly complicated curving system for it.

1 Like

The reason your ball is stuttering is because the ball’s physics are being simulated and calculated on the server, and your client can’t communicate with Roblox’s servers fast enough to make the movement appear smooth because of basic internet lag.

If you want to make the ball move smoothly, you have to simulate its physics on the client of the player who kicked the ball, and then replicate that to other players clients. The ball will still appear stuttery for other players, but the person who most recently kicked it will see it move clearly. That’s unfortunately a compromise you have to make.

To simulate the ball’s physics on the client, you have to set its “Network Ownership” to that client. You can do that on a server script with ball:SetNetworkOwnership(player).

After setting the network ownership to the client, you will apply the force to the ball from that client. The way you apply the force doesn’t matter, all physics on the ball will be simulated from your client if you set the network ownership correctly.

Just remember that it’s almost impossible to avoid lag entirely when using physics in multiplayer games.

2 Likes

I saw your earlier reply about applying and modifying the LinearVelocity, and @arbitiu 's and @zykobyte 's replies about Network Ownership. Here’s what I did so far:

function checkforBall(char)
	local ball = workspace:FindFirstChild("Ball")
	
	if ball then
		if (ball.Position - character.PrimaryPart.Position).Magnitude <= 6 then
			return ball
		end
	end
	
end

UIS.InputBegan:Connect(function(input, isTyping)
	if isTyping then
		return
	end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 and not cooldown then
		cooldown = true
		
		local ball = checkforBall(character)
		
		if ball then
			print("Ball found")
			
			local data = {
				["Ball"] = ball,
				["Character"] = character,
				["Action"] = "Shoot"
			}
			
			Events.BallHandlerEvent:FireServer(data)
		end
		
		wait(0.1)
		cooldown = false
	end
end)

For the server script, I did this, but the ball doesn’t move:

local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local Events = RS:WaitForChild("Events")
local Assets = RS:WaitForChild("Assets")
local GameValues = RS:WaitForChild("GameValues")

Events.BallHandlerEvent.OnServerEvent:Connect(function(player, data)
	local character = data.Character
	local ball = data.Ball
	
	ball:SetNetworkOwner()
	
	if player.Character == character then
		
		ball:SetNetworkOwner(player)
		
		local LinearVelocity = Instance.new("LinearVelocity", ball)
		LinearVelocity.MaxForce = math.huge
		LinearVelocity.LineDirection = character.PrimaryPart.CFrame.LookVector * 25
		LinearVelocity.LineVelocity = 25
		
	end
end)

Sorry if I did make some obvious mistakes, I’m not really familiar with the new velocities and such.

All good, simple mistake but I still make it sometimes, you just need to add this after creating the LinearVelocity:

local linearVelocityAttachment = Instance.new("Attachment")
linearVelocityAttachment.Parent = ball
LinearVelocity.Attachment0 = linearVelocityAttachment

Though, keep in mind, you want to create this in the ball to begin with but keep it disabled until someone kicks it, or at least that’s what I’d do.

Alternatively it can always be enabled but you keep the LineVelocity at 0 when no one kicks it, but this could be very slightly laggier cause it might still do the math for something that doesn’t actually move it at all, and if you wanted a funny gamemode with like 1000 balls or something for april fools (:shrug:, best example I could come up with) it could be laggy. (Tho that being said, Roblox might be smart enough to check the velocity first, I wouldn’t know lol)

2 Likes

Thank you for your reply,

For some reason the ball won’t budge. I tried changing the approach, but still to no avail. Did I do anything wrong regarding the properties of the velocity?

Thanks again!

2 Likes

Can I see the script? Or has it not changed?

1 Like