Knockback is laggy and choppy from the server. How can I optomize it to look smooth for all clients?

So I’m working on a fighting game, and of course you need good knockback in order for the game to be enjoyable. I have knockback, however it is incredibly choppy and late to the server. It looks fine on the client of the person that got hit, but everyone else sees a choppy, delayed “teleport” thing. I have tried a remote event that makes knockback handled on the client, but that didn’t help (unless I was doing something wrong). As always any and all help is appreciated. Thanks!

Code:

	root:SetNetworkOwner(nil)
	local direction = (root.Position - region.CFrame.Position).Unit
	root.Velocity = direction * KNOCKBACK_FORCE
	root:SetNetworkOwner(Players:GetPlayerFromCharacter(character))
1 Like

Can you send the full script? That’s probably not the full script, right?

Of course not! I just didn’t want to overwhelm anyone. Here is the full hitbox script:

local halfSize = Vector3.new(RADIUS1, RADIUS1, RADIUS1)
		local region = Region3.new(
			Player.Character.HumanoidRootPart.Position - halfSize,
			Player.Character.HumanoidRootPart.Position + halfSize
		)

		local partsInRegion = workspace:FindPartsInRegion3(region, nil, math.huge)
		local hitCharacters = {}

		for _, part in pairs(partsInRegion) do
			if part.Parent:FindFirstChild("Humanoid") then
				if part.Parent:FindFirstChild("Values") and part.Parent:FindFirstChild("Values").IFrames.Value == false then
					if part.Parent.Name ~= Player.Name then
						if HitboxesEnabled == true then
							local character = part.Parent
							if character and not table.find(hitCharacters, character) then
								table.insert(hitCharacters, character)

								local humanoid = character:FindFirstChild("Humanoid")
								local root = character:FindFirstChild("HumanoidRootPart")

								if humanoid and root then
									local damage = 5
									if SecureData[Player.UserId] then
										damage = damage + (SecureData[Player.UserId].Level * 0.1)
									end
									if character.Values.Parrying.Value == false then

										local val = Player.Character and Player.Character:FindFirstChild("Values")
										if val and val:FindFirstChild("DebugMode") and val.DebugMode.Value == true then
											local debugMsg = "Hit "..character.Name
											game:GetService("ReplicatedStorage").DebugMessage:FireClient(Player, debugMsg)
											local debugMsg2 = "Dealt "..damage.." damage"
											game:GetService("ReplicatedStorage").DebugMessage:FireClient(Player, debugMsg2)
										end

										humanoid:TakeDamage(damage)

										root:SetNetworkOwner(nil)
										local direction = (root.Position - region.CFrame.Position).Unit
										root.Velocity = direction * KNOCKBACK_FORCE1
										root:SetNetworkOwner(Players:GetPlayerFromCharacter(character))

										task.delay(0.001, function()
											Stun.StartRagdollTimer(character, 1)
											Stun.StartStunTimer(character, 1)
										end)
									else
										Player.Character.Humanoid:TakeDamage(damage * 0.2)
										character.Values.Parrying.Value = false
									end
								end
							end
						end
					end
				end
			end
		end

As you can probably see, i have a lot of values and stuff that you can just ignore. I’m only posting for the knockback issue.

This is all happening on the server right?

yep

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

It’s probably because you’re changing network owners rapidly, and when the network owner hasn’t gotten the message to start simulation or send data, it’ll look choppy (educated guess, may not be what’s happening).

Try using remotes or Mover constraints to let the player handle the velocity.

You could try firing a bindable event to all clients so it wouldn’t be choppy for them

Bindable events are for script to script communication, not cross client-server communication.

Huh. Never heard of them. What would i have to change to simulate a knockback with these?

Instead of applying the knockback on the server, tell the target client to apply the knockback on themselves.

What @nowodev is saying is that if you enact physics (i.e a BodyMover) onto a client, it automatically replicates across all clients. This is how changing walkspeed on the client will replicate that same walkspeed to all clients.

To be more precise, it replicates the instance to the client that owns the part, which then causes said client to apply that force, which is in turn replicated back to the server and to other clients.

That’s not anymore precise than what I said, in fact that’s more confusing and less precise. The most precise explanation is that physics enacted on a client is replicated to all other clients automatically.

The server can’t enact physics on parts it doesn’t own.

I have no idea how I would use these to simulate knockback. May I please have an example script?

Create a remote event in ReplicatedStorage, I’ll call it “ApplyKnockback” in the example but you can name it whatever you want.

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

local LOCALPLAYER = Players.LocalPlayer

ReplicatedStorage.ApplyKnockback.OnClientEvent:Connect(function(kbVelocity: Vector3)
	local character = LOCALPLAYER.Character
	if not character then return end

	local rootPart: BasePart? = character:FindFirstChild("HumanoidRootPart")
	if not rootPart then return end

	rootPart.AssemblyLinearVelocity = kbVelocity
end)

Then you can fire the target client on the server with the velocity you want.

1 Like

Why don’t you apply the knockback locally? The players’ position are automatically replicated to server, so setting it on the server is redundant.

I’ve already tried using a remote event and the same issue happens.

it may be because of the player’s ping.

oh ok I’ll try again later when I have a different tester available.

1 Like