Ragdoll Solution -- R15/Customizable ragdolls for use with Layered Clothing

So you got yourself some nice layered clothing drip, but dying makes your Robloxian shatter like glass into a million pieces. Not using R15 for your game? No problem! You can change it up with this system easily.

Introducing: Ragdoll Solution!

:cd: GET IT FREE HERE

Built on Layered Clothing

The initial idea of this project was to get a layered clothing to work on a ragdoll system to reduce the encounter of removing accessories on stock Roblox. The technology behind layered clothing is amazing, but its experience is omitted on player deaths or reset. This is here to solve that. I want to encourage users to enjoy layered clothing on their characters or games; and this means letting this project be free to use or modify on Roblox. If you created modified version you’re proud of, I’d love to see them on this thread!

Layered clothing also adds some performance weight, so I’ve also created some means to save it, turning this into a ragdoll system with added features. I suggest using it with 30 players in mind, and 60 players with performance options turned on.


Customizable *[1.0.8]

Here is how flexible this system is. If you want to use something that's not regular R15, then read this.
  • Limb Manager

HumanoidStarterSet Script

Every limbpart or group of limbparts can be given unique preloaded ballsocket values.

  1. If your rig has wing limbparts, you can give it separate ballsocket values from other limbparts by putting your wing’s limbparts names on a (hopefully easily) named table, and returning the table name from inside limbManager().

  2. limbManager() will then choose from the SOCKET_SETTINGS_R15 array, to assign all those part’s ballsocket settings.

  3. If a limbpart is not found, limbManager will return nil and the code will not proceed to look for something not included and continue safely. This is not intended to create a catch-all solution if all limbparts are read, but to allow deviations on similar rigs (like an R15, but spawned with one arm).

See how I grouped the hands and feets of the R15 parts, and gave them all the same ballsocket values, above. It doesn’t have to be linear or symmetrical by any means.

You can completely deviate from these R15 settings, and create a limbManager function for R6 rigs if you wish. However, if you load characters of multiple different rigs in your game, I recommend to create your own code to identify the character’s rig and load them each individually per character. This code does not do that, and assumes you will be using the same rig for every loaded player character.

If you do plan to edit this, see Performance Options to see important information.


*[1.0.8]

  • On Avatar Scaling

Inside Humanoid, the property AutomaticScalingEnabled shouldn’t be updated after ragdoll deaths due to weird bodyscaling and rig behaviors with parts changing on death.

Characters whose bodyscale values aren’t 1 on spawn and have changed will have problems. If you want characters of dynamic bodyscales, I recommend spawning them with all bodyscale values as 1, and then updating them right after they spawn. Make sure all changes are done and seen via serverside.

Characters of static bodyscales don’t seem to have this problem, but be aware of your usecase.


NPC Ragdolls and Player Ragdolls

The differences and likenesses on player ragdolls and NPC ragdolls.

NPCScript1
The two scripts that NPCs will use

If you want to use custom NPC rigs, then you may go with this in two directions. Have different HumanoidStarterSet scripts with different settings for each rig, or alternatively, treat them like players, and create different limbManagers and SOCKET_SETTING tables for each rig, keeping one HumanoidStarterSet script for all.

HumanoidStarterSet scripts, out of the box, are interchangable to R15 NPCs and players. Their ragdolls however, activate differently.

  • NPCs use a simple humanoid.Died to run various functions intended to make the system work. They are placed in their character model.

  • Players go through PlayersAdded and CharacterAdded, and a ServerEvent to activate their ragdoll on humanoid.Died. One script handles all this, and is placed in ServerScriptService.

Both ragdolls activate a set of preloaded velocity constraints to begin the collapse of the ragdoll on death. Note, that this is MANDATORY FOR PLAYERS. For some reason, serverside player humanoids do not recognize their newfound state of death until they are awoken through physical interaction (Yes I am serious with this raw unfiltered irony).

This is the point of the ServerEvent. It is to activate velocity constraints from a clientside signal without bothering players when not needing them.


Performance Options

See the included performance options and how you should handle a custom rig to them.

Explorer2

There are several performance options to stop ragdolls and humanoid from destroying your frames. Ignoring these will drop runtime heartbeat, and raise a sweaty gamer’s heartbeat instead. These can’t solve everything, so do your best to make sure players do not all die at once in the same frame.

On testing with all performance features on, 25 characters dying at once have made only 2.4% script activity max at a dropped heartbeat down to 47. Characters dying on separate frames spread the weight, with me seeing 1.5% script activity with no frame hiccups. In context, I have pretty turtle-speed 32GB ram running at 2133hz and an ol’ Intel 6th gen.


  • Load Control

charactersDied is tracked to make sure that players don’t ragdoll all at once. charactersDiedMax is the cap of players who died until the next character has to wait to ragdoll. The time to wait is hardcoded as (0.1 * charactersDied).

After dying if charactersDiedMax is full, dead characters will behave as PlatformStand instead of ragdolling. NPCs and players both add to charactersDied. The purpose of this is to reduce the amount of activated ragdolls for framerate reasons, and even give physics computation a break.

charactersDiedDecay is how long it takes for charactersDied to drop by 1 after a player dies. This is handled by diedCountDecay in ServerScriptService. The purpose of this is to relieve framerate drops incase many characters initiate indexes at once via code.


  • Ragdoll Freezing

ragdollFreezeTime is how long until a ragdoll anchors itself to stop interacting with physics. The conditions to freeze ragdolls is if their UpperTorso hasn’t moved a hardcoded 2 studs away from its last checked position. This repeats on ragdollFreezeTime’s seconds. All limbparts are then frozen if so.

You can enable or disable this feature with ragdollFreezeEnable. There is no function to unfreeze ragdolls.


  • Low Definition Ragdolls

There are low-definition ragdolls to ease on physics performance.

WARNING: This is set to FALSE right now due to unpredictable circumstances, but functions.

ragdollsExisted and ragdollsLdMax work hand-in-hand. If the server has
(ragdollsLdMax < ragdollsExisted) then NPC and Player ragdolls will break less joints in their ragdoll script (Not HumanoidStarterSet script). This is because of certain selected and found joints being destroyed, and isn’t done with any algorithm.

Here is the reason why I told you to read this part back there. This is not very advanced, and if custom rigs are being used, it should be written to accommodate new limbparts. It won’t crash, but failing to read any valid parts will mean no ragdolls.

There is another problem where ragdolls which disappear from workspace before removing a ragdollsExisted value, will leave it stuck. The script ragdollExistedReset in ServerScriptService is a quick solution to reduce the value by one until zero at a steady rate at 2 minute intervals.

You can choose to enable Ld ragdolls through checking true ragdollsLdEnable.


Collision Control

These ragdolls work with collision groups! While it can run without it, it may be better to set it.

Ragdollscriptset3

This system actively changes CollisionGroupIds. Living characters spawn with a CollisionGroupId of 2. Ragdolls are given a CollisionGroupId of 1. The above image shows that ragdolls (Named Body) will interact with eachother, but not with player characters (Named Players). You will have to create and assign these values in your own game through Studio.


HumanoidStarterSet Script

Excuse my cringe amount of assignments, but this brutal usage of dot operators to sprinkle noCollisionConstraints on certain limbs is really R15 specific. If its found that a rig has its own miniature earthquake, then disabling collisions on certain limbparts to others may solve it. My code already creates noCollisionConstraints with each part connected to the same joint already atop of this. This won’t be a problem if Body is unchecked to avoid colliding with itself in Collsion Groups.


Install Guide

Explorer

:cd: GET IT FREE HERE

To install, enter edit mode in this place, and copy them into your game so the paths look exactly the same. You can have a game work with the stock settings with no change, but I still recommend having Collsion Groups set. NPC scripts are included in the place. Also included in the place, but not part of this system is a keybinded L to reset, and a Bloxy Cola tool.


Notes

  • This system works under the implication that HumanoidRootPart is never unattached from characters.
  • Players unequip tools and empty backpacks on death. This is to greatly reduce desync on clothes and players.
  • There were regular occurances of desync on ragdolls with layered clothes. This was fixed through a hacky mean through updating the accessory.
  • Layered clothing won’t work for R6 rigs.
Release Notes
1.0.8
  • CustomPhysicalProperties changes set to be closer to regular vanilla values to prevent disruption of gameplay.
  • Attempt hotfix for scaling issues with some package and custom characters on death. This is for both NPCs and Players.
1.1.0
  • Stopped the playing of animations upon the death of humanoid on both NPCs and Players
  • Changes of some stock settings. RagdollsLdEnable is false and ragdollsLdMax is now 3. Prior settings had them not as described.

Thanks!

If there is a lot of interest, I’ll update this to include some more wanted features. Crediting isn’t necessary, but you can do so by including Ragdoll Solution and my username in a credits section.

If you wish to directly support my work on the platform, please consider buying my UGC items! :shopping:

78 Likes

Thanks for this resource. I can see you put in a ton of work and many people will use this. Thanks for the contribution and keep up the good work!

4 Likes

This module is very nice, but i didnt seem to find it easy “rigging” the custom humanoids.
I would recommend using the Motor6D (Joints) to easily make ragdoll system.

Here is a module of mine which rigs every single humanoid in existence (if rigged correctly).

local module = {}


if game:GetService("RunService"):IsServer() then
	local PhysicsService = game:GetService("PhysicsService")
	PhysicsService:CreateCollisionGroup("Players")
	PhysicsService:CreateCollisionGroup("Collider")
	PhysicsService:CollisionGroupSetCollidable("Players","Collider",false)
	
	function module.RigPlayer(char)
		local hum : Humanoid = char:WaitForChild("Humanoid")
		hum.BreakJointsOnDeath = false
		for _,v in pairs(char:GetDescendants()) do
			if v:IsA("Motor6D") then
				local BallSocket = Instance.new("BallSocketConstraint",v.Part0)
				BallSocket.Name = "BC"
				v.Part1.Massless = true
				v.Part0.Massless = true
				v.Part1.CanCollide = false
				v.Part0.CanCollide = false

				PhysicsService:SetPartCollisionGroup(v.Part1,"Players")

				local Holder = Instance.new("Part",v.Part1)
				PhysicsService:SetPartCollisionGroup(Holder,"Collider")
				Holder.Size = v.Part1.Size/1.5
				Holder.CFrame = v.Part1.CFrame
				local Weld = Instance.new("WeldConstraint",Holder) Weld.Part0 = v.Part1 Weld.Part1 = Holder
				Holder.Transparency = 1
				Holder.Massless = true

				local att1 = Instance.new("Attachment",v.Part0) att1.Name = "AttRag"
				local att2 = Instance.new("Attachment",v.Part1) att1.Name = "AttRag"
				att2.Position = v.C1.Position
				att1.WorldPosition= att2.WorldPosition

				BallSocket.Attachment0 = att1
				BallSocket.Attachment1 = att2
			end
		end
				
		hum.Died:Connect(function()
			for _,v in pairs(char:GetDescendants()) do
				if v:IsA("Motor6D") then
					v:Destroy()
				end
			end
		end)
	end
else
	warn("Can not rig from the Client")
end

return module
3 Likes

This is really nice! My code does indeed index through character parts and motor6ds to connect the limbs, as suggested. It’s just that the limbs’s ballsocket values and noCollisionConstraints are all different, which is why I included limbManager() and SOCKET_SETTINGS to handle creating twist and angle limits. Without it, I think the bodies will look very noodle-like.

2 Likes

WOW
It’s simpler and has features that lacks from my ragdoll system
It makes installment easier, in FACT it makes easier for artificial euphoria physics engine (No more complex hardcoded euphoria muscle build)
Definitely use it since i stopped updating ragdoll so mine rotted away all of performance.

2 Likes

Your ragdoll system doesn’t account for avatar packages :

When my avatar dies, it gets stretched out & some limbs are disconnected.

1 Like

This is a great resource, thanks for creating this. I’ve got only one problem though…

I would love to use DOGU15 with this ragdoll, but for some reason, it separates DOGU15 limbs. Any Idea on how I could fix this?

It seems like the problem for Noble_Draconian and yours seem to rely on Avatar scaling growing or shrinking proportionally when a scaling value is differently to 1. This is very strange and should be patched.

In non-broken cases I’ve seen avatar packages and even Dogu15 itself work in good conditions. I’m gonna see some fixes for this.

Well, the video looks amazing, I’ll check it out when I have time.

I’ve just finished a hotfix for what I think may have fixed those issues. If the problems persist, I will investigate further, and would like a Studio file or rig reproducing this problem.

In addition, I have included some findings about how avatar scaling works with the system, and have posted my discoveries in the “Customizable” section.

Alright, I’ll check it out right now. If I still have the issue I’ll give you a studio file.

EDIT: The hotfix has fixed the issue of DOGU15 limbs separating. Thank you for this great ragdoll resource.

1 Like

Looks really good, also just wanted to say the ‘trailer’ was really neat XD.

1 Like

Your hack for resyncing layered clothing doesn’t actually work, is there more to getting Layered Clothing working on Ragdolls? I have my own ragdoll system and once the original avatar’s motors are destroyed layered clothing ceases to function, even with the wrap target method.

Heya. Can you describe the problem, what isn’t working, and when it happens? I haven’t had much luck in trying to reproduce it from scratch.

As it turns out, you don’t need that resync at all as long as all of your constraints remain in the original parts. I.E replacing the “Neck” motor with a ball-socket also named “Neck”.

Updated this after getting a message about animations playing after death on NPC ragdolls. I am implementing a fix on both player and NPC scripts so they are in parity. This adds a new function to be run after humanoid dies.

v1.1.0
  • Stopped the playing of animations upon the death of humanoid on both NPCs and Players
  • Changes of some stock settings. RagdollsLdEnable is false and ragdollsLdMax is now 3. Prior settings had them not as described.

Apparently, Roblox animations will continue to play even after the character has died on humanoids in some cases. It’s just that we’ve never encountered this as a problem because our limbs usually exploded before.

1 Like

Is there any way to make this work without killing the npc / player

I have yet to try ragdolls on living players. If I recall, there are some quirks with collisions on players that would require some patching up. I hope the answer is “not yet”, instead of “no” with this system.

Can you make it so we can press a key to ragdoll and unragdoll please

its toggleable ?.-.-.-.-.-…-.-.-.-.-.-

1 Like