Hey everyone,
for some time now I’ve been trying to make a really smooth ragdoll / knockback system, but always came out laggy, or having some delay.
The thing is, there’s this one game called Ultimate Battlegrounds which basically has perfect, seamless ragdoll: now I don’t really want to worry about it being exploitable, I just wish for some help on how to achieve this effect.
Any help is much appreciated, thank you!
Lag is normally caused during server-client replication. So you want to do it on the client to prevent lag. This does make your game vulnerable to exploits but you said that’s not your concern so
The thing about ragdolling on the client, is that it works only for your client, but other players will see you freezed until you unragdoll.
The workaround I had for this was ragdolling the client, then send a remote to the other clients which then would create a clone of the ragdoll character and ragdoll that clone on their client, but the problem with this one is that if you apply knockback on the clone, it will end up in a different position thus causing the clone to teleport once the character will unragdoll
Yes these are valid concerns, but lag is something that cannot be avoided entirely. There can be very,very little, but not none. Perhaps optimisation is a good way to reduce lag on the server.
Another way is to ragdoll the desired player in the function connected to the all clients event instead of creating a clone ie. rag doll the player after firing all clients on their side
Example if you don’t understand my bad English
ragdollevent:FireAllClients()
ragdollevent.OnClientEvent:Connect(function()
— run code to rag doll player here
end)
I’ve tried already making the ragdoll on each client, but the problem with it is that others will see you freezed until you unragdoll:
https://i.gyazo.com/babb2f0152c0d969ffbfa6218b94825f.mp4
Obviously you’re moving the hrp so other clients will only see that move. But that’s not important.
At this point I’d advise you to try some ragdoll modules out there. Popular games also use them quite a bit. Here are some I’ve found
Ofc you don’t need to use them but other people have nice things to say about them so I thought you’d rather find them better
I have looked many recources on the dev forum, but they all turned out to be the same (laggy, jittery).
Also, I think many popular games such as TSB or Heroes Battlegrounds suffer from this laggy ragdoll effect, all of them besides Ultimate Battlegrounds - Roblox. This game has the best ragdoll system as far as I know (probably exploitable), and it is buttery smooth, for you and for other clients aswell.
Then they most likely turned a blind eye on the exploitability in favour of smooth gameplay
Yeah that’s what I’m saying, I’m not really concerned about exploiters, I just wanted some help on how they’ve managed to achieve this.
After some testing on their game, turns out they are cloning the character on each client and applying ragdoll and knockback to the clone: after trying this myself, the knockback on each client would always end up in a different position?
Could you show an example?
From what i’m getting, if you are applying the same velocity towards the same direction, there shouldn’t be anything causing desync between clients, sure at the end of the ragdoll, your character might be a little bit offsetted for other clients, but when it stands up, the position shouldn’t be all that different from the ragdolls end position.
This is happening:
https://i.gyazo.com/d052f4e8d250c6da9b59bc32529daf7d.mp4
when the client ragdolls, it sends e remote to the server with the RootPart’s cframe.
The server then fires a remote to everyone with: ragdoll character, RootPart’s cframe, knockback (vector3), time (number).
Then each client proceeds to clone the ragdoll character, cframe it to the RootPart’s cframe parameter, then ragdolls it with knockback and time
Also, you can see in the video that when other clients try to cframe the clone to the original ragdoll, it just teleports back for some reason?
You should post the code for the cframing because without it I don’t think anyone here would be able to help you with that. There is a lot of reasons why the cframe won’t replicate. Like what I just posted where I can’t correctly keep a part rotated without a coroutine.wrap function and then if you use that, the cframe never actually updates except for within that function.
Yeah sorry about that:
Client:
local RagdollHandler = require(game.ReplicatedStorage.RagdollHandlerV2)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid: Humanoid = character.Humanoid
local camera = workspace.CurrentCamera
humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
local function cloneCharacter(_character: Model): Model
_character.Archivable = true
local clone: Model = _character:Clone()
_character.Archivable = false
return clone
end
local function setCharacterTransparency(_character: Model, transparency: number)
local numberToBool = {true, false}
for _, object in _character:GetDescendants() do
if (object:IsA("BasePart") and object.Name ~= "HumanoidRootPart") or object:IsA("Decal") then
object.Transparency = transparency
elseif object:IsA("Accessory") then
object.Handle.Transparency = transparency
elseif object:IsA("BillboardGui") then
object.Enabled = numberToBool[transparency + 1]
end
end
end
local function cloneRagdoll(_character: Model, rootCFrame, knockback, time)
local clone = cloneCharacter(_character)
clone.Name = _character.Name.."_RAGDOLL_CLONE"
clone.Parent = workspace
clone.PrimaryPart.CFrame = rootCFrame
setCharacterTransparency(_character, 1)
RagdollHandler:Ragdoll(clone, knockback, time)
end
game.ReplicatedStorage.CharacterClone.OnClientEvent:Connect(cloneRagdoll)
game.UserInputService.InputBegan:Connect(function(i)
if i.KeyCode == Enum.KeyCode.F then
game.ReplicatedStorage.Ragdoll:FireServer(character.HumanoidRootPart.CFrame)
end
end)
Server:
game.ReplicatedStorage.Ragdoll.OnServerEvent:Connect(function(plr, rootCFrame)
game.ReplicatedStorage.CharacterClone:FireAllClients(plr.Character, rootCFrame, {Direction = Vector3.yAxis * 500}, -2)
end)
It definitely has something to do with the rootCFrame variable. I would do some prints and check where your character is mysteriously “teleporting back” as you called it. You can grab the position it is going to and manipulate the script from there to get it to go to your original clone position
the rootCFrame parameter is correct, it’s the same on every client, the problem comes when the character gets teleported to the rootCFrame, as the root part of the clone gets teleported correctly, but then starts to “re-align” with the rest of the body, thus causing that teleport back effect.
I’ve also tried anchoring it when cframing it to the rootCFrame, and it turned out to be correct.
Also, after some testing on the knockback, turns out the main problem could be due to that root part teleport back effect, since when you apply some force to it, as the root part teleports back it loses velocity and ends up getting a different knockback when it fully moved back, I don’t really know why this is happening though…
Ok update:
I’ve managed to fix that rootpart teleport problem, there had to be a bit of wait time (Heartbeat) before ragdolling the clone, but now the biggest problem is that there’s a big teleport when activating the ragdoll, and still, the clone would end up in different positions on every client for some reason:
https://i.gyazo.com/5ff4b272fe75a2b9ca789b5ff72de3df.mp4
bumping this as I still haven’t found no solution to the different knockback problem
Update: After some tests I’ve noticed that at the very beginning of the ragdoll, each clone on each client has the exact same property (primary part cframe, linear velocity, angular velocity etc…), but then, once get some force applied to them, (I made a loop to print those three properties at different times, roughly every 0.2 seconds) they all turned out to be different from each other???
I don’t really understand how this is possible though, they are getting the exact same cframe, exact same linear velocity and force at the beginning, yet they are able to change direction mid-air?
I’m legit completely lost