Ragdoll On Client; is it doable?

So what I’m trying to achieve is the same thing roblox does with their RbxCharacterSounds, it tracks playerAdded and sets up the sound for each player, no stress on the server and it’s perfectly synced. Now what I want to do is have the server create constraints for everybody, and have them enabled on client, and when a ragdoll is initiated, i track it, so when new players join it replicates for them as well. I have a way of doing anti cheat which can save me from exploiters, but I’m just asking if it’s doable or not.

1 Like

Clients can simulate their own, local physics objects like Ragdolls, however:

I see this as potentially causing issues. The server will become the owner of the character upon the player dying, and so unless you generate some undefined behavior by deleting the HumanoidRootPart on the Client (thus creating a new, Client-side Assembly comprised of Server Parts), the Client will expect the Server to simulate the ragdoll and not properly apply it’s own physics. Personally, when I ventured into Client-side ragdolls, I had the Client clone the character to avoid any potential Network Ownership problems. You can try what you described for yourself though, but it’s something that just doesn’t feel quite right to me.

Yep, I confirm the server ownership makes it so that simulating another player’s Ragdoll character on your client only runs smoothly when you’re in a few studs of them.

So when you cloned the character to use that as a client-sided Ragdoll, where did you store their actual character? Also, how is the client-created Ragdoll clone under network ownership of the client?

1 Like

I :Destroy’d it. Not like the client needs it anymore. Every other Client creates duplicates before :Destroying it as well, and the Server also does so after a few seconds.

The Client automatically assumes ownership over parts it created…

This works for Ragdoll deaths, as the real character of another player won’t be needed, but what if the ragdoll needs to be toggled on and off, then would you instead use :Remove() so that it still exists but outside of the DataModel? Then after the Ragdoll is disabled set its parent back to workspace?

1 Like

In that case, duplicates shouldn’t be used. If you need to maintain control over the ragdoll, you’d be overcomplicating everything with Client-side versions. The only reason I’m using them is because ragdolls do not serve a gameplay purpose in my game. It’s just a visual effect, and does not need to be synchronized, but toggle-able ragdolls need to be synchronized so that the player can smoothly re-gain control of their character.

:Remove() is deprecated and I’m pretty sure it’s actually slower than just .Parent = nil.

I think there is a potential way of doing this, When each character is added that is of a player, Pre-Create Joints on the player’s character. Now when the ragdoll happens, fire all the clients, including the ownership one, and tell them to de-enable motor 6d joint and enable the Ragdoll Joints (Hinge constraints or ball and socket.) as the current player is in charge, it updates all other characters on other clients.

How can the server become the owner of the character upon dying? I don’t think that the character is ever the owner of a player’s plr.Character unless manually specified.

Well, when you die and your character explodes, there’s a very visible stutter where the physics are frozen for a little bit. This could be either the player losing ownership of the character, after all, the “character” no longer exists to the Physics engine (there aren’t any Constraints to keep everything under the same Assembly), or just a network pause as the Server affirms the Client has ownership of all the parts that comprise of the character.

I personally think the former makes more sense. The way Network Ownership works is per-Assembly, and Assemblies are just a group of parts connected via Constraints that share the same AssemblyRootPart. All parts under the Assembly are owned by the Network Owner of the Root Part, and if they are all disconnected and become their own individual Assemblies, there’s no longer a common Root Part to tell them who is supposed to be simulating them. Unless there’s some flimsy logic forcing the ownership of every single part under the Character to be owned by the player and not just the Humanoid’s RootPart while they are alive, then the physics pause indicates the Server takes over completely.

The ragdoll state is triggered in part by player controls, thus the ragdolling of the player must, and does happen client-sided. If alternatively the ragdolling happens on the server, I’d need to use remote events which update the ragdoll too slowly. Switching rapidly between being and not being ragdolled would glitch and not work properly. Therefore a server-sided approach is off the table.

Because of this, I need to do the ragdoll of the local character on the client then also replicate the correct ragdoll state of all other characters in the game on the client. Because I need the local player to have network ownership of other player’s characters, I just struggle to see a way around this problem.

How do I simulate other player’s characters in a ragdoll state?

Can you test out this simple demo I made to see if it is responsive enough for your usecase?
responsive-ragdoll.rbxl (128.7 KB)

I tested with 500ms of ping (Studio Settings>Network>Diagnostics>Incoming Replication Lag = 0.5), and it was still instantly responsive. The biggest issue is when you press the Ragdoll key (R) then quickly press the un-Ragdoll key (E) before the Server catches up, causing you to ragdoll for an instant before going back to normal, but I’m sure it’s not that difficult to fix.

(And, I don’t know what I did, but the animations are broken for some reason. Weird.)

How it works is simple: When the ragdoll is triggered Server-side by the green block regularly turning red, the Server activates the ragdoll joints on it’s side, and also sends a message to the Client to do so too, while forcing the Ownership of the character’s parts to the Client to ensure no Network Ownership weirdness happens. When the ragdoll is triggered Client-side by pressing the Ragdoll button, it’ll turn on the ragdoll joints first and tell the server to do the same.

Thanks for sending this example place, I tested it and it worked fine. But because the Ragdoll system I was using was server-sided before I moved it to the client, I can explain the problem with housing it on the server.

The delay between the client and server is minute most of the time, but my game has precise physics calculations that can’t afford to be affected by the differing speeds of client-server communication. For example this diving code on the client:

repeat task.wait() until rootpart.AssemblyLinearVelocity.Y < -1

The Ragdoll needs to activate immediately after this repeat until statement’s condition is satisfied. As this—and other game mechanics related to it—all occur on the client due to the all dealing with character controls, the server will very rarely be able to kick in time, leading to variable results in the physics.

1 Like