I have a ragdoll system that doesn’t affect the humanoid in anyway but listen for PlatformStand.Changed.
When I die normally, my manual respawn script and ragdoll script works. However, when PlatformStand is already enabled (the ragdoll is active), both scripts don’t get calls from Humanoid.Died at all (I checked with print). This causes the player to stay dead and not respawn at all.
The funny thing is, localscripts can still detect when the humanoid died, and act appropriately, while server-side ones don’t at all.
I’m a bit lost, what exactly are you attempting to accomplish with PlatformStand?
There’s not much I can do to help unless I’m able to see what your scripts look like. Can you explain how this system is supposed to work, what problem(s) you’re trying to eliminate, and the code you’ve written?
PlatformStand is used by my ragdoll system as an alternative to the “ragdoll” humanoid state. It just listens to whenever platformStand is changed so it can activate and de-activate the ragdoll. Here is my ragdoll script.
local humanoid = script.Parent:WaitForChild("Humanoid")
local playerName = humanoid.Parent.Name
local debris = game:GetService("Debris")
humanoid.BreakJointsOnDeath = false
humanoid:GetPropertyChangedSignal("PlatformStand"):Connect(function()
if humanoid.PlatformStand == true then
for index,joint in pairs(script.Parent:GetDescendants()) do
if joint:IsA("Motor6D") then
local socket = Instance.new("BallSocketConstraint")
local a1 = Instance.new("Attachment")
local a2 = Instance.new("Attachment")
a1.Parent = joint.Part0
a2.Parent = joint.Part1
socket.Parent = joint.Parent
socket.Attachment0 = a1
socket.Attachment1 = a2
a1.CFrame = joint.C0
a2.CFrame = joint.C1
socket.LimitsEnabled = true
socket.TwistLimitsEnabled = true
joint.Enabled = false
end
end
for i,v in pairs(game.ReplicatedStorage:WaitForChild("RagdollKit"):GetChildren()) do
local vclone = v:Clone()
vclone.Parent = script.Parent
vclone.CFrame = script.Parent[v.WeldName.Value].CFrame
local w = Instance.new('Weld')
w.Part0 = vclone
w.Part1 = script.Parent[v.WeldName.Value]
w.Parent = vclone
end
humanoid.AutoRotate = false
elseif humanoid.PlatformStand == false then
for index,joint in pairs(script.Parent:GetDescendants()) do
if joint:IsA("Motor6D") then
joint.Enabled = true
end
end
for i,v in pairs(script.Parent:GetChildren()) do
if v:FindFirstChild("Attachment") then
for i,v in pairs(v:GetChildren()) do
if v.Name == "Attachment" then
v:Remove()
end
end
end
if v:FindFirstChild("BallSocketConstraint") then
for i,v in pairs(v:GetChildren()) do
if v:IsA("BallSocketConstraint") then
v:Remove()
end
end
end
end
for i,v in pairs(script.Parent:GetChildren()) do
if v.Name == "DELETE" then
v:Remove()
end
end
humanoid.AutoRotate = true
end
end)
humanoid.Died:Connect(function()
if humanoid.PlatformStand == false then
humanoid.PlatformStand = true
end
wait(9) --keep this updated to the respawn delay in the respawnScript
local test = (humanoid.Parent:GetChildren())
if not game.Workspace.Ragdolls:FindFirstChild(playerName) then
local folder = Instance.new("Folder")
folder.Parent = game.Workspace.Ragdolls
folder.Name = playerName
end
local testing = Instance.new("Model",game.Workspace.Ragdolls[playerName])
testing.Name = playerName
for i = 1, #test do
local child = test[i]
child:Clone()
child.Parent = testing
end
end)
The “delete” parts are simply for making the ragdoll physics better, and the bottom part is so the ragdolls are cloned to stay after death.
Again, this works normally, until I die while being ragdolled before-hand (which makes the humanoid.Died function not detectable by server scripts).
I wasn’t able to find any issues with the ragdoll script. Do any errors or warnings return in the output as your code runs?
Are you running this code in a local or server-sided script? Humanoid.Died may not be working properly because of the changes you’re making to the humanoid, and where you’re making them. Is the humanoid’s parent or instance ever changed? Have you tried printing any data that applies to the humanoid as it dies and ragdolls?
There’s no changes being made to the humanoid (apart from autorotate and platformstand, but that’s irrelevant). It’s in a server side script.
My problem is that if you’re ragdolled already → THEN die, the server side scripts can’t detect it. I tried using print to debug it, and nothing came up when the humanoid died on the server-side end. Of course no errors would occur, since the event supposedly didn’t even happen according to the server scripts.
Right, have you checked if localscripts can still see Humanoid.Died? If so, have you tried checking for it on the client and then passing it onto the other clients (excluding the local player) instead of checking on the entire server?
This method may be able to help with client performance and ultimately user experience as high ping will not affect the local player, only allowing delay of the visibilty of those changes for other players in the server.
(This WOULD mean you would need to reengineer your ragdoll script a bit, specifically making it run locally and then passing on a replication of those changes to all other clients other than the LocalPlayer)
I tried doing that, but it didn’t work. I made a simple remote event that fires from a local script when you die, and instead made it so that (on the server scripts i mentioned) they use:
event.OnServerEvent:Connect(function(player)
if player.Character:FindFirstChild("Humanoid").Health <= 0 then
-- code here
end
end)
Instead of using remote events looping back to let the server know when the player has died, check directly on the client in a localscript. Here’s an example:
game.Players.LocalPlayer.Character:FindFirstChild("Humanoid").Died:Connect(function)
--code here
end)
When this event is called, the code inside the connected function will run and ideally apply ragdoll physics to the character DIRECTLY within the function on the CLIENT. This should be followed by a replication of these changes sent directly to each client connected to the server. (again, obviously excluding the LocalPlayer)
Do remember though, use this: RemoteEvent:FireClient(AllOtherClients)
not: RemoteEvent:FireAllClients()
Otherwise, you’re gonna be making the same changes to the local player twice… which isn’t ideal.
The problem is that the server side scripts that NEED to be on the server can’t detect it. I use a manual spawning system to spawn players manually due to how my game works.
Can I see what your manual spawning script looks like? There is most definitely a way to implement this type of system into the method I previously suggested.
local respawnDelay = 10
local rs = game:GetService("ReplicatedStorage")
game.Players.CharacterAutoLoads = false
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
-- find the humanoid, and detect when it dies
character:WaitForChild("Humanoid").Died:Connect(function()
print("died")
wait(respawnDelay)
player:LoadCharacter()
end)
end)
player:WaitForChild("teamValue").Changed:Connect(function()
player:LoadCharacter() -- load the character for the first time
end)
end)
Besides, how would I make the ragdolls stay after death on the server side per your method?
Your automatic spawning script looks okay to me, but you may need to tweak it a bit as you make changes to other parts of the whole system.
With the method I explained, both the server and the client will work together to create a functional system. When the humanoid’s health reaches zero and the client reads that it has died, the signal sent to the server to make these changes to all other clients may also clone the character directly in the server, which DOES include the local player. (obviously)
You’re gonna have to reengineer your entire system a bit to get it to work properly this way, but it’s totally worth it if you’re not only fixing issues, but increasing overall performance as well.
Here’s a little timeline to give you a better idea of what I’m going for:
When the player’s character dies, (even in ragdoll) the event (Humanoid.Died) fires in a LocalScript and runs a function.
In this function, the server is fired with a remote event containing information like the player instance who’s character died.
The server receives this event with the information required to perform all server-sided tasks. The server-sided script will know which player has died, which allows it to run a for loop with RemoteEvent:FireClient(AllOtherClients) running each time to go through each player in the server. If the player instances name is equal to the player’s character who died’s name, it should skip that user. Following this action, the server will clone the player who died’s character after respawn so it stays even after death.
The players’ clients that receive the remote event will apply the same changes the player who died’s client made to its own player’s character, only on their client. (once again… duh)
All this would be synced up with your manual character load script, which I’m sure you have the hang of.
Do NOT do this. Using RemoteEvent:FireAllClients() will also fire the event on the client of the player who died, which will cause the same changes to be made on the one client twice… which could cause a plethora of issues.