DevXylo's IK Ragdoll Method (Inverse Kinematics Ragdoll Module)

Do you struggle with ragdolls? Do you need a new way of making ragdolls? Are you looking for a good ragdoll module? You should try this module out!

Introducing, Inverse Kinematics Ragdoll Module! This module uses my method of making IK Ragdolls. It’s the 2023 way of making ragdolls, It has better collisions and it’s less buggier than the previous method (BallSocketConstraint Method)

Module Link

IK Ragdoll Module (DevXylo Method)

Module Guide:

Step 1 - Requiring the module.
You will need to require the module in order to use the functions.

local ragdollModule = require(game:GetService("ServerStorage"):WaitForChild("DevXylo's IK Ragdoll Method"))

Step 2 - Ragdolling the rig/player.
Now you’re simply going to call the function :IKRagdoll() and put in the rig/character in order to make it ragdoll.

local request = ragdollModule:IKRagdoll(game:WaitForChild("Players"):GetPlayers()[1].Character) --  This line is going to return a table full of parts, attachments and values, while ragdolling the rig/character.

local returnedTable

returnedTable = request --  The important table for Unragdolling.

Step 2 - Unragdolling/Rebuilding
Now you’re going to use the returnedTable variable to unragdoll/rebuild the rig/character.

ragdollModule:Rebuild(game:WaitForChild("Players"):GetPlayers()[1].Character, returnedTable)

Full Module Script:

local physService = game:GetService("PhysicsService")

physService:RegisterCollisionGroup("IgnoreHitbox")
physService:CollisionGroupSetCollidable("IgnoreHitbox", "IgnoreHitbox", false)
physService:CollisionGroupSetCollidable("IgnoreHitbox", "Default", false)

local ragdollCollisionGroup = "IgnoreHitbox"

local limbList = {
	"Head",
	"UpperTorso",
	"LowerTorso",
	"LeftFoot",
	"LeftLowerLeg",
	"LeftUpperLeg",
	"RightFoot",
	"RightLowerLeg",
	"RightUpperLeg",
	"LeftHand",
	"LeftLowerArm",
	"LeftUpperArm",
	"RightHand",
	"RightLowerArm",
	"RightUpperArm",
	"HumanoidRootPart"
}

local module = {}
local instances = {}

local function CollisionGroup(c)
	local storedLimbCollisionGroups = {
		["Head"] = "",
		["UpperTorso"] = "",
		["LowerTorso"] = "",
		["LeftFoot"] = "",
		["LeftLowerLeg"] = "",
		["LeftUpperLeg"] = "",
		["RightFoot"] = "",
		["RightLowerLeg"] = "",
		["RightUpperLeg"] = "",
		["LeftHand"] = "",
		["LeftLowerArm"] = "",
		["LeftUpperArm"] = "",
		["RightHand"] = "",
		["RightLowerArm"] = "",
		["RightUpperArm"] = "",
		["HumanoidRootPart"] = ""
	}
	for _, limbName in pairs(limbList) do
		local limb = c:FindFirstChild(limbName)
		if limb then
			storedLimbCollisionGroups[limbName] = limb.CollisionGroup
			limb.CollisionGroup = ragdollCollisionGroup
		end
	end
	return storedLimbCollisionGroups
end

local function CreateHitbox(c)
	local hitbox = Instance.new("Model", c)
	for _, limbName in pairs(limbList) do
		local limb = c:FindFirstChild(limbName)
		if limb then
			local limbHitbox = Instance.new("Part", hitbox)
			limbHitbox.Name = limb.Name
			limbHitbox.CanCollide = true
			limbHitbox.Size = limb.Size
			limbHitbox.Transparency = 1
			local hitboxWeld = Instance.new("WeldConstraint", limbHitbox)
			limbHitbox.CFrame = limb.CFrame
			hitboxWeld.Part0 = limb
			hitboxWeld.Part1 = limbHitbox
		end
	end
	return hitbox
end

function CheckObjects(c)
	local humanoid = c:WaitForChild("Humanoid")
	local primaryPart = c.PrimaryPart
	local liveRagdollTargetRefs = c:WaitForChild("Humanoid"):FindFirstChild("LiveRagdollTargetRefs")
	local IKParts = workspace:FindFirstChild("IKParts")
	if liveRagdollTargetRefs == nil then
		liveRagdollTargetRefs = Instance.new("Folder")
		liveRagdollTargetRefs.Parent = c:WaitForChild("Humanoid")
		liveRagdollTargetRefs.Name = "LiveRagdollTargetRefs"
	end
	if IKParts == nil then
		IKParts = Instance.new("Folder")
		IKParts.Parent = workspace
		IKParts.Name = "IKParts"
	end
end

function Velocity(c, hitbox)
	local players = game:GetService("Players")
	local humanoid = c:WaitForChild("Humanoid")
	local primaryPart = hitbox:WaitForChild(c.PrimaryPart.Name)
	local debris = game:GetService("Debris")
	humanoid.PlatformStand = true
	local velocityAttachment = Instance.new("Attachment", primaryPart)
	local velocity = Instance.new("AngularVelocity", velocityAttachment)
	velocity.Attachment0 = velocityAttachment
	velocity.MaxTorque = 1500
	velocity.AngularVelocity = primaryPart.CFrame.RightVector * 50
	velocity.RelativeTo = Enum.ActuatorRelativeTo.World
	velocity.ReactionTorqueEnabled = true
	debris:AddItem(velocityAttachment, 0.2)
end

function CreateRopeTarget(name, ikstart, ikend, joint, c)
	local humanoid = c:WaitForChild("Humanoid")
	local part = Instance.new("Part")
	part.Transparency = 1
	part.Size = Vector3.new(0.5, 0.5, 0.5)
	part.CFrame = ikend.CFrame
	part.Name = name
	part.Parent = workspace:WaitForChild("IKParts")
	local at = Instance.new("Attachment")
	at.Parent = part
	at.Visible = false
	local r = Instance.new("RopeConstraint")
	r.Length = 6
	r.Visible = false
	r.Attachment0 = joint
	r.Attachment1 = at
	r.Parent = part
	r.Visible = false
	local ik = Instance.new("IKControl")
	ik.Name = name
	ik.Type = Enum.IKControlType.Position
	ik.ChainRoot = ikstart
	ik.EndEffector = ikend
	ik.Target = part
	ik.Parent = humanoid
	local ob = Instance.new("ObjectValue")
	ob.Name = name
	ob.Value = part
	ob.Parent = humanoid:WaitForChild("LiveRagdollTargetRefs")
	table.insert(instances, part)
	table.insert(instances, at)
	table.insert(instances, r)
	table.insert(instances, ik)
	table.insert(instances, ob)
	return part
end

function module:IKRagdoll(c : Model)
	CheckObjects(c)
	instances = {}
	local humanoid = c:WaitForChild("Humanoid")
	local primaryPart = c.PrimaryPart
	local walkSpeed = nil
	local jumpPower = nil
	local storedCollisionGroups = CollisionGroup(c)
	local hitbox = CreateHitbox(c)
	primaryPart.Massless = true
	if humanoid.RigType == Enum.HumanoidRigType.R15 then
		c:WaitForChild("LowerTorso"):WaitForChild("Root").Enabled = false
	elseif humanoid.RigType == Enum.HumanoidRigType.R6 then
		c:WaitForChild("HumanoidRootPart"):WaitForChild("RootJoint").Enabled = false
	end
	table.insert(instances, hitbox)
	walkSpeed = humanoid.WalkSpeed
	jumpPower = humanoid.JumpPower
	humanoid.WalkSpeed = 0
	humanoid.JumpPower = 0
	if humanoid.Health > 0 then
		humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
	end
	coroutine.wrap(Velocity)(c, hitbox)
	CreateRopeTarget(c.Name .. "_RagIKTarget_RH", c.RightUpperArm, c.RightHand, c.UpperTorso.RightShoulderRigAttachment, c)
	CreateRopeTarget(c.Name .. "_RagIKTarget_LH", c.LeftUpperArm, c.LeftHand, c.UpperTorso.LeftShoulderRigAttachment, c)
	CreateRopeTarget(c.Name .. "_RagIKTarget_RF", c.RightUpperLeg, c.RightFoot, c.LowerTorso.RightHipRigAttachment, c)
	CreateRopeTarget(c.Name .. "_RagIKTarget_LF", c.LeftUpperLeg, c.LeftFoot, c.LowerTorso.LeftHipRigAttachment, c)
	return {instances, walkSpeed, jumpPower, storedCollisionGroups}
end

function module:Rebuild(c : Model, restoredTable : "table")
	local players = game:GetService("Players")
	local humanoid = c:WaitForChild("Humanoid")
	local primaryPart = c.PrimaryPart
	local instancesTable = restoredTable[1]
	local savedWalkSpeed = restoredTable[2]
	local savedJumpPower = restoredTable[3]
	local restoredCollisionGroupTable = restoredTable[4]
	for _, instance in pairs(instancesTable) do
		instance:Destroy()
	end
	for limbName, collisionName in pairs(restoredCollisionGroupTable) do
		local limb = c:FindFirstChild(limbName)
		if limb then
			limb.CollisionGroup = collisionName
		end
	end
	humanoid.PlatformStand = false
	primaryPart.Anchored = true
	primaryPart.CFrame = CFrame.new(primaryPart.Position) * CFrame.new(0, c:GetExtentsSize().Y / 2, 0) * CFrame.Angles(0, math.rad(90), 0)
	primaryPart.Anchored = false
	primaryPart.Massless = false
	if humanoid.RigType == Enum.HumanoidRigType.R15 then
		c:WaitForChild("LowerTorso"):WaitForChild("Root").Enabled = true
	elseif humanoid.RigType == Enum.HumanoidRigType.R6 then
		c:WaitForChild("HumanoidRootPart"):WaitForChild("RootJoint").Enabled = true
	end
	humanoid.WalkSpeed = savedWalkSpeed
	humanoid.JumpPower = savedJumpPower
	humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end

return module

This Module is BETA so feedback is always appreciated

Best regards, DevXylo.

Q/A:

Q1: Can you animate the ragdoll?
A1: I actually saw a topic where a Developer asked if you could animate the ragdoll. The answer is yes. The ragdoll edits the position of every limbs using Inverse Kinematics, so you can still animate the ragdoll.
Q2: Are there any bugs/glitches?
A2: Yes, there can be physics glitches and bugs, so don’t expect the module to be glitch-free.

39 Likes

May you show a video and picture of what your module is capable of?

6 Likes

Sure! You can move it like this using inverse kinematics, rope constraints and attachments (That’s what the module does)

6 Likes

Recent “Rebuild” Updates!


UPDATE 09-09-2023

Rebuilding is now able to predict the Getup CFrame using GetExtentsSize!

CFrame.new(c.PrimaryPart.Position) * CFrame.new(0, c:GetExtentsSize().Y / 2, 0) * CFrame.Angles(0, math.rad(90), 0)


UPDATE 09-06-2023

Rebuild is now saving animations and replaying them!

2 Likes

New Improvements/Fixes!


UPDATE 11-09-2023

Now LinearVelocity is being used to move the ragdoll!

local velocityAttachment = Instance.new("Attachment", c.PrimaryPart)
local velocity = Instance.new("LinearVelocity", velocityAttachment)
velocity.Attachment0 = velocityAttachment
velocity.MaxForce = (1234 * 5678 * 90 * 1234) * (1234 * 5678 * 90 * 1234) velocity.VectorVelocity = c.PrimaryPart.CFrame.LookVector * -5 game:GetService("Debris"):AddItem(velocityAttachment, 0.2)


FIXES

  • Added Network Ownership to fix lag!
  • Fixed permanent walk animation and jump animation when rebuilding!
  • Platform Stand is now being used to make the ragdoll fall down correctly!
  • Fixed a few Humanoid States!
8 Likes

Looks cool, but for people like me I wouldn’t use it just because the code looks very messy I recommend when open sourcing your module u make it organized, clean, neat

3 Likes

Thanks for the advice. I can probably try to clean up the script and make it look more organized.

2 Likes

DEVXYLO’S IK RAGDOLL METHOD V2!

I improvised the module and added more functions, I also beautified and optimised the code more. This is a new and improved version of the method, it has bug fixes and it won’t give you a headache when looking at the previous messy code!

FIXES

  • Removed unnecessary checks!
  • Added more variables!
  • Fixed animation playing permanently again!
  • Removed Network Ownership!
  • Replaced long lines of codes with functions!
  • Replaced LinearVelocity with AngularVelocity!
  • Replaced Physic State to Ragdoll State!
  • Added Hitboxes!
  • Added Collision Groups!

INSTALL/UPDATE HERE!

2 Likes

Your Module is great,

However when calling the Modules:IKRagdoll(character) method right after the player dies, It will bug around and fully stop working.

2 Likes

There might be an issue with disconnecting the ragdoll after the character had been deleted. If this is not the case, then a temporary solution would be to check if the character is a descendant of the game.

if Character:IsDescendantOf(game) then

I hope this fixes your problem incase the creator doesn’t find out in time. :slight_smile:

1 Like

This is a common error that occurs when the Network Ownership API thinks that the parent of the character is not in workspace, perhaps you could change the C variable to c = workspace:WaitForChild(c.Name) or you could also try out @AwesomeAnemii’s solution, I’m currently in Europe, so my timezone may be different. Tomorrow I could try to make sure this doesn’t happen. Thanks. :slight_smile:

I’ll make a reply in the devforum page when I fix this error, so you can stay notified whenever I update my module.

Alright, so I fixed the error. The reason that you couldn’t respawn was because that the ragdoll state replaced the death state without me knowing. I have replaced the network ownership API with something else. If you want the fixed version, you can reinstall the module. Sorry for the inconvenience.

I don’t understand what this module does, does it has a custom physics engine for making ragdolls?, or not because I see you mention the use of LinearVelocity, I don’t really understand what it is.

1 Like

It’s basically a new way of making the player ragdoll (fall down), it uses inverse kinematics to make the player ragdoll instead of the old method (BallSocketConstraints). LinearVelocity is just an extra touch to the module, it’s there just to ensure that the player actually falls down. This module could be useful for making realistic death instead of the player breaking joints. I hope I made you understand.

1 Like

I’m sorry I still don’t understand how does it works with inverse kinematics, is it using a custom physics engine along with custom collision solver for that?.

1 Like

It doesn’t use a custom physic engine, it still uses Roblox’s physic engine, roblox recently added Inverse Kinematics, so I made a ragdoll module using roblox’s new inverse kinematics.

It uses collision groups while adding hitboxes to the player, so the player can ragdoll more realistically. The reason for collision groups is just to make sure that the player doesn’t glitch with the hitboxes. So, the real limbs in your character can ignore the hitbox limbs. The reason for hitboxes is because your roblox arms normally would not collide with anything, while your legs, head, and torso would, so to fix this problem, I added hitboxes and collision groups.

I had no idea Roblox had added an IK controller instance thing, Holy cow, I see what this resource does now, I’m definitely going to be downloading this for my ragdolls since I used skinned meshes.

2 Likes

Is it possible to use this on other players/NPCS? I.e if they get hit?

1 Like

Yes, it works on other rigs as well.

Is there any way to remove / disable the use of RopeConstraints to move the limbs?

I noticed, when the player dies while moving and the ropeTargets get created, it makes the player instantly drop to the floor, not retaining the velocity it had beforehand.

This becomes very apparent when the player is flying for example at a steady speed, dying causes the player to instantly start dropping to the floor where it died and not retaining its velocity, making the effect become unrealistic and look very bad.

^ This is caused by the creation of The parts that connect the Limbs to the Parts, Since the Parts get created without their velocity being set It causes the whole body to effectivly freeze and drop down

If possible, I suggest making the ragdolls somehow work without the Ropes and find a solution to the Velocity problem, (Maybe port the Module over to the client instead of the server to use)

1 Like