Unable to create a smooth knockback

Hello, I am currently creating a combat system and well, it’s finally time to do the knockback however i’m running into issue when it come to making it responsive and smooth.

So, from the server I am firing all clients the knockback strength, which character should be knockback and the player who initiated the knockback.

So that mean the knockback calculation is done from the client.

Here what it looks :

On the right side (The player who get knockbacked) it’s really smooth because obviously, due to network ownership they are calculating their own physics. However on the attacker side (player who initiated the knockback) it look laggy.

Even tho I am firing all clients, I tried setting the network owner to the server but it was a really bad idea because it looked even more laggy, I tried doing knockback on the server but it still look laggy, I know this issue has been around here for a long time.

I also tried creating a welded part that is parented to each character rootpart then setting the network owner to the server and the knockback is applied to that part, but same result. So I came to the conclusion that this was useless since it’s calculating the whole character moving and not a single part.

But games like battlegrounds are able to achieve responsive and smooth knockback, thank you if you are able to help me.

Try firing only to the victim’s client and knockbacking from there

I tried doing that but same result too :smiling_face_with_tear:

Fascinating, may i see the code good sir?

Client side :

local function Knockback(CharToKB, AttackerChar, KnockbackForce)
	local VictimRootPart = CharToKB:FindFirstChild("HumanoidRootPart") or CharToKB:WaitForChild("HumanoidRootPart", 5)  :: BasePart
	local AttackerRootPart = AttackerChar:FindFirstChild("HumanoidRootPart") or AttackerChar:WaitForChild("HumanoidRootPart", 5)
	
	if not AttackerRootPart or not VictimRootPart then
		return
	end
	
	VictimRootPart:ApplyImpulse(AttackerRootPart.CFrame.LookVector * KnockbackForce * VictimRootPart.AssemblyMass)
end

Server side :

function Character.Knockback(self : Object, AttackerCharObj, KnockbackStrength)
	local AttackerRootPart = AttackerCharObj.RootPart :: BasePart
	local AttackerHumanoid = AttackerCharObj.Humanoid

	if not KnockbackStrength or not AttackerRootPart or AttackerHumanoid.Health <= 0 or self.Humanoid.Health <= 0 then
		return
	end

	-- define if it's a npc or not
	local AttackerChar = AttackerCharObj.Character
	local VictimChar = self.Character
	
	if not AttackerChar or not VictimChar then 
		return
	end
	
	local Attacker = Players:GetPlayerFromCharacter(AttackerChar)
	local Victim = Players:GetPlayerFromCharacter(VictimChar) 
	
--	local PlayerToFire = Victim
	
	if not Attacker then 
		-- incase the attacker is a NPC (example : Attacking dummies or smth)
		AttackerCharObj.RootPart:SetNetworkOwner(Victim)
	end
	
	if not Victim then 
		-- make it so the NPC physics look smooth on the attacker client
		-- Client will calculate all physics related to the NPC
		-- Problem is that during the knockback, client can exploit the NPC
		
		--PlayerToFire = Attacker
	
		if self.Threads.Network then
			task.cancel(self.Threads.Network)

			self.Threads.Network = nil
		end
		
		self.RootPart:SetNetworkOwner(Attacker) 
		
		self.Threads.Network = task.delay(KnockbackStrength * 0.015, function()
			-- revert the networkship back to default
			self.RootPart:SetNetworkOwnershipAuto() 
		end)
	end
	
	
	--[[
		print(PlayerToFire,	AttackerChar, KnockbackStrength)
		KnockbackRemote:FireClient(
		PlayerToFire, 
		-- If it's a NPC we fire the attacker instead
		-- Firing the player so it apply knockback on itself if it's not a NPC
		VictimChar,
		AttackerChar, -- Player who attacked 
		KnockbackStrength
	)
	]]

	KnockbackRemote:FireAllClients(
		-- If it's a NPC we fire the attacker instead
		-- Firing the player so it apply knockback on itself if it's not a NPC
		VictimChar,
		AttackerChar, -- Player who attacked 
		KnockbackStrength
	)
end

Drop this in a part with touch and run into it. Possibly you could adapt this to work for you.

local db=true
script.Parent.Touched:Connect(function(hit)
	if db and hit.Parent:FindFirstChild("Humanoid") then db = false
		local character = hit.Parent
		local torso = character:FindFirstChild("LowerTorso") or
			character:FindFirstChild("Torso")
		if(torso)then
			local bv = Instance.new("BodyVelocity")
			bv.Parent = torso bv.MaxForce = Vector3.one * 100000
			bv.Velocity = character.Head.CFrame.LookVector *
				-80 + character.Head.CFrame.UpVector * 80
			wait(0.033) bv:Destroy()
		end	task.wait(0.33)
		db = true
	end
end)

Not sure if this will work for you… but it will sure kick you back, with a nice little arc.

Try this:

local function Knockback(CharToKB, AttackerChar, KnockbackForce)
    local VictimRootPart = CharToKB:FindFirstChild("HumanoidRootPart") or CharToKB:WaitForChild("HumanoidRootPart", 5) :: BasePart
    local AttackerRootPart = AttackerChar:FindFirstChild("HumanoidRootPart") or AttackerChar:WaitForChild("HumanoidRootPart", 5)
    
    if not AttackerRootPart or not VictimRootPart then
        return
    end
    
    local direction = AttackerRootPart.CFrame.LookVector
    local vectorForce = Instance.new("VectorForce")
    vectorForce.Force = direction * KnockbackForce * VictimRootPart.AssemblyMass
    vectorForce.RelativeTo = Enum.ActuatorRelativeTo.World
    vectorForce.ApplyAtCenterOfMass = true
    vectorForce.Parent = VictimRootPart
    
    game:GetService("Debris"):AddItem(vectorForce, 0.2)
end

XD