I am trying to swap out all body parts of an R15 rig. The problem is that intermittently the character dies. You can reproduce this by opening the following place in Studio, clicking Play, and waiting a few minutes
local player = game:GetService("Players").PlayerAdded:Wait()
function applyBodyPart(character, r15Parts)
local humanoid = character:FindFirstChild("Humanoid")
local accoutrements = {}
for _, child in pairs(character:GetChildren()) do
if child:IsA("Accoutrement") then
child.Parent = nil
table.insert(accoutrements, child)
end
end
for _, part in pairs(r15Parts) do
local oldPart = character:FindFirstChild(part.Name)
oldPart:Destroy()
part:Clone().Parent = character
end
character.Humanoid:BuildRigFromAttachments()
for _, accoutrement in pairs(accoutrements) do
accoutrement.Parent = character
end
end
player.CharacterAdded:connect(function(character)
while character:FindFirstChild("Humanoid") and character.Humanoid.Health > 0 do
wait(2)
local r15Parts = game:GetService("ServerStorage"):FindFirstChild("R15")
applyBodyPart(character, r15Parts:GetChildren())
end
error("DIED")
end)
Inside of ServerStorage I have a model called R15 which contains all the body parts for the character.
Edited to remove the line anchoring the HumanoidRootPart, as that was not necessary to repro
then you can just re-enable it once your conversion is completed… I believe I’ve gotten around your issue by doing this before - I could be remembering incorrectly.
I believe :SetStateEnabled replicates to the server if you were to call it from the client (also, the documentation on it does not state it does not replicate, as it normally would), however given your examples you are calling it on the server so it should replicate through regardless.
I’d say you’re safe just calling it from the server directly before this loop:
humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
-- your loop inside of applyBodyPart()
for _, part in pairs(r15Parts) do
local oldPart = character:FindFirstChild(part.Name)
oldPart:Destroy()
part:Clone().Parent = character
end
humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
again, I didn’t edit your repro and test, I could be totally wrong!
Isn’t there a function under humanoid now for replacing R15 body parts? It would probably be better to use that instead of BuildRigFromAttachments for this, though I have never tried it out myself.
If the function works how I think it does, then there should be no need to go through the process of disabling the dead state.
Toggling the dead state immediately before and after the operation is not enough - the character still dies. I’m guessing the death is only detected at the next physics step or something like that. Still looking for solutions.
In my game I have BuildRigFromAttachments() inside the for loop, so it rebuilds after each part is replaced. I remember having this problem but haven’t noticed it in a while, and i just did some testing and wasn’t able to trigger the death. I still think it happens with lag though but can’t test it.
Consider also reparenting the character’s humanoid to nil and back while you’re doing the swap. This stupid trick saved me back in 2010 and I think I’m still using it.
You can swap all parts you want to replace after using SetStateEnabled and call Humanoid:BuildRigFromAttachments() afterwards. Then reenable the death state.
You might have already found a way to do this or forgotten about this issue, but I will say my solution here because I didn’t find it anywhere else: set Humanoid.RequiresNeck = false while you are doing the replacement. I have set so my characters never require a neck just to be sure, but I think it should be enough.