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))
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.
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.
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.
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.