Cannot enable .CanCollide from Server script

  1. What do you want to achieve? Keep it simple and clear!
    I want to make it so that all the limbs of the character have .CanCollide enabled via a script.

  2. What is the issue? Include screenshots / videos if possible!
    This is a ragdoll engine. It all works just fine, however, when the character’s clone ragdolls, the limbs i.e. arms and legs have .CanCollide disabled and it won’t turn on no matter what I do.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried doing obj.CanCollide = true in the for loop in the script but it didnt work.

For simplicity, the script included here is the original ragdoll engine that does not have my modifications that I made in an attempt to enable .CanCollide.

  1. Replication steps:
  • Make a server script in ServerScriptService
  • Add the following code:
--> SERVICES <--
local Players = game:GetService("Players")

--> SETUP <--
local Connections = {} :: {[Player]: {RBXScriptConnection}}

--> FUNCTIONS <--

local function RagdollCharacter(character: Model)
	character.Archivable = true
	local corpse = character:Clone()
	corpse.Parent = game.Workspace
	corpse.PrimaryPart = corpse:FindFirstChild("HumanoidRootPart")

	-- Make corpse non-player controlled
	for _, obj in corpse:GetChildren() do
		if obj.Name == "Head" or obj.Name == "Torso" or obj.Name == "Left Arm" or obj.Name == "Right Arm" or obj.Name == "Left Leg" or obj.Name == "Right Leg" or obj.Name == "HumanoidRootPart" then
			obj.CanCollide = true
			obj.Anchored = false
		elseif obj:IsA("Humanoid") then
			obj.BreakJointsOnDeath = false
			obj.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
			obj.PlatformStand = true
		end
	end

	-- Ragdoll the corpse
	for _, motor in corpse:GetDescendants() do
		if motor:IsA("Motor6D") then
			local socket = Instance.new("BallSocketConstraint")
			local a0 = Instance.new("Attachment")
			local a1 = Instance.new("Attachment")

			a0.CFrame = motor.C0
			a1.CFrame = motor.C1
			a0.Parent = motor.Part0
			a1.Parent = motor.Part1

			socket.Attachment0 = a0
			socket.Attachment1 = a1
			socket.Parent = motor.Part1.Parent

			motor.Part1.Velocity = Vector3.new(0, 0, 0)
			motor.Part1.RotVelocity = Vector3.new(0, 0, 0)

			motor.Enabled = false
			motor.Part0 = nil
			motor.Part1 = nil
		end
	end

	-- Apply impulse for a dramatic effect
	task.spawn(function()
		local torso = corpse:FindFirstChild("Torso") or corpse.PrimaryPart
		if torso then
			torso:ApplyImpulse(torso.CFrame.LookVector * 200)
		end
	end)

	-- Destroy corpse after 20 seconds
	task.delay(120, function()
		if corpse then
			corpse:Destroy()
		end
	end)

	return corpse
end

local function SetupCharacter(char: Model, player: Player)
	local hum = char:WaitForChild("Humanoid") :: Humanoid
	hum.BreakJointsOnDeath = false

	hum.Died:Once(function()
		-- Create corpse
		local corpse = RagdollCharacter(char)

		-- Hide the original character
		for _, obj in char:GetChildren() do
			if obj:IsA("Humanoid") then
				obj.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
			else
				obj:Destroy()
			end
		end

		-- Spectate the corpse
		local camera = workspace.CurrentCamera
		if camera then
			camera.CameraSubject = corpse:FindFirstChildOfClass("Humanoid") or corpse.PrimaryPart
		end
	end)
end

local function SetupPlayer(player: Player)
	Connections[player] = {}

	-- Setup Character
	local char = player.Character or player.CharacterAdded:Wait()
	SetupCharacter(char, player)

	table.insert(Connections[player], player.CharacterAdded:Connect(function(newChar)
		SetupCharacter(newChar, player)
		local camera = workspace.CurrentCamera
		if camera then
			camera.CameraSubject = newChar:FindFirstChildOfClass("Humanoid") or newChar.PrimaryPart
		end
	end))
end

--> EVENT HANDLING <--
for _, player in Players:GetPlayers() do
	task.spawn(SetupPlayer, player)
end

Players.PlayerAdded:Connect(SetupPlayer)

Players.PlayerRemoving:Connect(function(player)
	if Connections[player] then
		for _, connection in Connections[player] do
			connection:Disconnect()
		end
		Connections[player] = nil
	end
end)
  • Launch the game and reset/die.
1 Like

I found out that adding a tiny delay does the trick! Try this: `–> SERVICES ←
local Players = game:GetService(“Players”)

→ SETUP ←
local Connections = {} :: {[Player]: {RBXScriptConnection}}

→ FUNCTIONS ←

local function EnableCollision(corpse: Model)
for _, obj in corpse:GetChildren() do
if obj:IsA(“BasePart”) then
obj.Anchored = false
obj.CanCollide = true
end
end
end

local function RagdollCharacter(character: Model)
character.Archivable = true
local corpse = character:Clone()
corpse.Parent = game.Workspace
corpse.PrimaryPart = corpse:FindFirstChild(“HumanoidRootPart”)

-- Make corpse non-player controlled

for _, obj in corpse:GetChildren() do
	if obj:IsA("Humanoid") then
		obj.BreakJointsOnDeath = false
		obj.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
		obj.PlatformStand = true
	end
end

-- Ragdoll the corpse
for _, motor in corpse:GetDescendants() do
	if motor:IsA("Motor6D") then
		local socket = Instance.new("BallSocketConstraint")
		local a0 = Instance.new("Attachment")
		local a1 = Instance.new("Attachment")

		a0.CFrame = motor.C0
		a1.CFrame = motor.C1
		a0.Parent = motor.Part0
		a1.Parent = motor.Part1

		socket.Attachment0 = a0
		socket.Attachment1 = a1
		socket.Parent = motor.Part1.Parent

		motor.Part1.Velocity = Vector3.new(0, 0, 0)
		motor.Part1.RotVelocity = Vector3.new(0, 0, 0)

		motor.Enabled = false
		motor.Part0 = nil
		motor.Part1 = nil
	end
end



-- Apply impulse for a dramatic effect
task.spawn(function()
	local torso = corpse:FindFirstChild("Torso") or corpse.PrimaryPart
	if torso then
		torso:ApplyImpulse(torso.CFrame.LookVector * 200)
	end
end)

-- Destroy corpse after 20 seconds
task.delay(120, function()
	if corpse then
		corpse:Destroy()
	end
end)

task.wait(0.01)
EnableCollision(corpse)

return corpse

end

local function SetupCharacter(char: Model, player: Player)
local hum = char:WaitForChild(“Humanoid”) :: Humanoid
hum.BreakJointsOnDeath = false

hum.Died:Once(function()
	-- Create corpse
	local corpse = RagdollCharacter(char)

	-- Hide the original character
	for _, obj in char:GetChildren() do
		if obj:IsA("Humanoid") then
			obj.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
		else
			obj:Destroy()
		end
	end

	-- Spectate the corpse
	local camera = workspace.CurrentCamera
	if camera then
		camera.CameraSubject = corpse:FindFirstChildOfClass("Humanoid") or corpse.PrimaryPart
	end
end)

end

local function SetupPlayer(player: Player)
Connections[player] = {}

-- Setup Character
local char = player.Character or player.CharacterAdded:Wait()
SetupCharacter(char, player)

table.insert(Connections[player], player.CharacterAdded:Connect(function(newChar)
	SetupCharacter(newChar, player)
	local camera = workspace.CurrentCamera
	if camera then
		camera.CameraSubject = newChar:FindFirstChildOfClass("Humanoid") or newChar.PrimaryPart
	end
end))

end

→ EVENT HANDLING ←
for _, player in Players:GetPlayers() do
task.spawn(SetupPlayer, player)
end

Players.PlayerAdded:Connect(SetupPlayer)

Players.PlayerRemoving:Connect(function(player)
if Connections[player] then
for _, connection in Connections[player] do
connection:Disconnect()
end
Connections[player] = nil
end
end)`

1 Like

Thanks, it worked! It was probably some desync issue or something.

Hey actually I have another problem:

--> SERVICES <--
local Character: Model = script.Parent
local Humanoid: Humanoid = Character:FindFirstChildOfClass("Humanoid")

--> SETUP <--
Humanoid.BreakJointsOnDeath = false
Humanoid.RequiresNeck = false

--> Create `IsRagdoll` BoolValue if it doesn’t exist <--
local RagdollValue = Character:FindFirstChild("IsRagdoll")
if not RagdollValue then
	RagdollValue = Instance.new("BoolValue")
	RagdollValue.Name = "IsRagdoll"
	RagdollValue.Parent = Character
end

--> Stores original Motor6D joints for restoring later <--
local MotorStorage = {}

--> FUNCTIONS <--

-- Ensure all body parts are unanchored and collidable
local function EnableCollision(model: Model)
warn('ENALINBING COLLISSIOSN')
	for _, obj in model:GetDescendants() do
		if obj:IsA("BasePart") then
			obj.Anchored = false
			obj.CanCollide = false
			task.wait()
			obj.CanCollide = true
		elseif obj:IsA("Accessory") then
			print(obj.Name)
		--	task.wait()
		--	obj:FindFirstChild("Handle").CanCollide = true
			task.wait(0.01)
			obj:FindFirstChild("Handle").CanCollide = false
			warn(obj:FindFirstChild("Handle").Name)
			task.wait()
			if obj:FindFirstChild("Handle").CanCollide == true then 
				warn("COLLISSION OM")
			else
				warn("COLLISSION OFF")
			end
		end
	end
end

-- Converts Motor6D's into BallSocketConstraints
local function ReplaceJoints()
	-- Store and disable Motor6Ds instead of deleting them
	
	for _, motor in Character:GetDescendants() do
		if motor:IsA("Motor6D") then
			if not MotorStorage[motor.Name] then
				MotorStorage[motor.Name] = {Motor6D = motor, Part0 = motor.Part0, Part1 = motor.Part1}
			end
			motor.Enabled = false

			local socket = Instance.new("BallSocketConstraint")
			local a0 = Instance.new("Attachment")
			local a1 = Instance.new("Attachment")

			a0.CFrame = motor.C0
			a1.CFrame = motor.C1
			a0.Parent = motor.Part0
			a1.Parent = motor.Part1

			socket.Attachment0 = a0
			socket.Attachment1 = a1
			socket.Parent = motor.Part1.Parent
			socket.Name = "RagdollConstraint"

			-- Store the created constraints
			MotorStorage[motor.Name].Socket = socket
			MotorStorage[motor.Name].Attachment0 = a0
			MotorStorage[motor.Name].Attachment1 = a1
		end
	end

	-- Apply impulse for realism
	task.spawn(function()
		local torso = Character:FindFirstChild("Torso") or Character.PrimaryPart
		if torso then
			torso:ApplyImpulse(torso.CFrame.LookVector * 200)
		end
	end)
	
	Humanoid.PlatformStand = false
	task.wait(0.01)
	Humanoid.PlatformStand = true
	
	task.wait(0.01)
	EnableCollision(Character)
	Humanoid.AutoRotate = false -- Prevents unwanted rotation
end

-- Restores original Motor6D joints (un-ragdoll)
local function ResetJoints()
	if Humanoid.Health < 1 then return end
--	Humanoid.PlatformStand = true

	for _, data in pairs(MotorStorage) do
		local motor = data.Motor6D
		if motor then
			-- Re-enable Motor6D joints
			motor.Part0 = data.Part0
			motor.Part1 = data.Part1
			motor.Enabled = true
		end
		-- Remove ragdoll constraints
		if data.Socket then data.Socket:Destroy() end
		if data.Attachment0 then data.Attachment0:Destroy() end
		if data.Attachment1 then data.Attachment1:Destroy() end
	end

	Humanoid.PlatformStand = true
	task.wait(0.01)
	Humanoid.PlatformStand = false
	
	Humanoid.AutoRotate = true
end

-- Handles ragdoll toggling
local function Ragdoll(value: boolean)
	if value then
		ReplaceJoints()
	else
		ResetJoints()
	end
end

--> EVENT HANDLING <--
RagdollValue:GetPropertyChangedSignal("Value"):Connect(function()
	Ragdoll(RagdollValue.Value)
end)

Here, the character looks like it’s having a stroke from how much it bounces around while ragdolled. I did some testing and turns out the Handle BasePart inside accessories turn collissions on when ragdolled (but normally they’re off) and disabling those collissions fixes it. However, I cannot do it from this script, just doesn’t work.

Hey! I apologize for the weird formatting this and last time (I’m new to posting on the forum). I simply did some checks to see if the handle’s parent was an accessory and turn off collisions if it was!

→ SERVICES ←
local Character: Model = script.Parent
local Humanoid: Humanoid = Character:FindFirstChildOfClass(“Humanoid”)

→ SETUP ←
Humanoid.BreakJointsOnDeath = false
Humanoid.RequiresNeck = false

→ Create IsRagdoll BoolValue if it doesn’t exist ←
local RagdollValue = Character:FindFirstChild(“IsRagdoll”)
if not RagdollValue then
RagdollValue = Instance.new(“BoolValue”)
RagdollValue.Name = “IsRagdoll”
RagdollValue.Parent = Character
end

→ Stores original Motor6D joints for restoring later ←
local MotorStorage = {}

→ FUNCTIONS ←

– Ensure all body parts are unanchored and collidable
local function EnableCollision(model: Model)
task.wait()
warn(‘ENALINBING COLLISSIOSN’)
for _, obj in model:GetDescendants() do
if obj:IsA(“BasePart”) and not obj.Parent:IsA(“Accessory”) and obj.Name ~= “HumanoidRootPart” then
obj.CanCollide = true
end
end
end

– Converts Motor6D’s into BallSocketConstraints
local function ReplaceJoints()
– Store and disable Motor6Ds instead of deleting them

for _, motor in Character:GetDescendants() do
	if motor:IsA("Motor6D") then
		if not MotorStorage[motor.Name] then
			MotorStorage[motor.Name] = {Motor6D = motor, Part0 = motor.Part0, Part1 = motor.Part1}
		end
		motor.Enabled = false

		local socket = Instance.new("BallSocketConstraint")
		local a0 = Instance.new("Attachment")
		local a1 = Instance.new("Attachment")

		a0.CFrame = motor.C0
		a1.CFrame = motor.C1
		a0.Parent = motor.Part0
		a1.Parent = motor.Part1

		socket.Attachment0 = a0
		socket.Attachment1 = a1
		socket.Parent = motor.Part1.Parent
		socket.Name = "RagdollConstraint"

		-- Store the created constraints
		MotorStorage[motor.Name].Socket = socket
		MotorStorage[motor.Name].Attachment0 = a0
		MotorStorage[motor.Name].Attachment1 = a1
	end
end

-- Apply impulse for realism
task.spawn(function()
	local torso = Character:FindFirstChild("Torso") or Character.PrimaryPart
	if torso then
		torso:ApplyImpulse(torso.CFrame.LookVector * 200)
	end
end)

Humanoid.PlatformStand = false
task.wait(0.01)
Humanoid.PlatformStand = true

task.wait(0.01)
EnableCollision(Character)
Humanoid.AutoRotate = false -- Prevents unwanted rotation

end

– Restores original Motor6D joints (un-ragdoll)
local function ResetJoints()
if Humanoid.Health < 1 then return end
– Humanoid.PlatformStand = true

for _, data in pairs(MotorStorage) do
	local motor = data.Motor6D
	if motor then
		-- Re-enable Motor6D joints
		motor.Part0 = data.Part0
		motor.Part1 = data.Part1
		motor.Enabled = true
	end
	-- Remove ragdoll constraints
	if data.Socket then data.Socket:Destroy() end
	if data.Attachment0 then data.Attachment0:Destroy() end
	if data.Attachment1 then data.Attachment1:Destroy() end
end

Humanoid.PlatformStand = true
task.wait(0.01)
Humanoid.PlatformStand = false

Humanoid.AutoRotate = true

end

– Handles ragdoll toggling
local function Ragdoll(value: boolean)
if value then
ReplaceJoints()
else
ResetJoints()
end
end

→ EVENT HANDLING ←
RagdollValue:GetPropertyChangedSignal(“Value”):Connect(function()
Ragdoll(RagdollValue.Value)
end) HANDLING ←
RagdollValue:GetPropertyChangedSignal(“Value”):Connect(function()
Ragdoll(RagdollValue.Value)
end)`

1 Like

Thanks, it worked! However, I resorted to buying a ragdoll module for a few dollars instead of trying to make my own, that worked way better. But I’ll still credit you for finding the solution to the original problem!

Also, to format code in DevForum, do it like so:

Your code goes here
Your code goes here
Your code goes here
Your code goes here

image

Thanks! I’m still new to the forum so this is very helpful. This is actually my first solution!

1 Like

Aww, happy to help! Keep going :slight_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.