New client sided errors:
Error 1
Error 2
Both of these should be fixed now. I also noticed that the CanCollide fix I made earlier caused a new CanCollide problem (CanCollide being true on the client after spawning when it should be false). That should also be fixed now.
Apparently packagelinks are now automatically removed from free models for whatever reason. I know that the package update features didn’t work for free models even before, but I used PackageLink.PackageId
for checking that the instance with name “GeneralUtility” or “RemoteEventSystem” is actually the correct package and not just an unrelated instance that happens to have the same name.
However, that check is practically unnecessary so I just removed it. If you now add updated versions of RagdollSystem and RemoteEventSystem, they should work.
I am getting this error and do not know why, it’s pretty important so I can use this system.
Testing function
Could you post a screenshot of the entire stack trace of the error?
I had abandoned the place file, but I recreated the issue,
The place file is here.
ragdolltest.rbxl (443.5 KB)
I don’t know if it’s an issue but the characters I have are R15 characters, sometimes with no HumanoidDescription, and sometimes they have a lot of accessories equipped to them.
The primary part is set to the humanoidrootpart and humanoid set to r15
Thanks, the place file helped a lot.
The reason for the error was that my code assumed that only bodyparts have Attachments with “RigAttachment” in their names. So such an attachment in an accessory caused the error. I added a condition in assignRigAttachmentsToBodypartNodes
for skipping rig attachments that are descendants of accessories.
I also fixed some other problems that I happened to find that are irrelevant to this problem (listed in the changelog).
Also, since the code for ragdolling the character and the initialization code are in different scripts in the test place and there’s nothing controlling which runs first, that sometimes causes a different error because other functions in RagdollSystem are not meant to be called before calling the initialization functions.
That’s excellent update! Thanks for the fix! Also, I understand the initialization setup must be done first. I will get back to this soon, I disabled my old ragdoll system and am hoping to upgrade to this one.
I had a feeling it was due to the accessories, but that’s just how accessories work, you have a attachment inside of it that tells the humanoid api to attach the accessory offset from the existing attachment inside the bodypart. So that’s a good fix.
I just tested it and it works great! I’m about to implement it into my combat AIs. But one last question what does future support look like for bones? What are the obstacles for using bones?
I have no experience with using bones but I suppose it would be necessary to create invisible collision parts with rig attachments, create the physics constraints between these collision parts and find the correct bone for each rig attachment pair. And when a joint is in ragdoll state, the CFrame of the bone of that joint would be updated every frame using the CFrame of the joint’s rig attachment that is parented to the part lower in the animation hierarchy.
If a skinned character consists of multiple parts but not as many parts as there are animated joints, then I should probably support breaking joints that connect collision parts for two different skinned parts (and also disable whatever is keeping the skinned parts together and reparent the skinned parts) but throw an error if the user tries to break a joint between collision parts that are for the same skinned part.
The user would have to create the collision parts and their RigAttachments beforehand. Perhaps I would also require creating RigidConstraints or something between the RigAttachments to define which pairs of attachment belong together although that may be unnecessary as I could just use the similarity of WorldCFrames of rig attachments to figure out which of them are pairs as long as the rig attachment pairs are positioned in the same world position when RagdollStructure.createStructure is called.
My current code assumes that each pair of connected bodyparts has a Motor6D but if I add support for bones then I can’t make this assumption anymore, so many changes to the code would be needed. Unfortunately I’m not sure if I’ll add support for bones and even if I do, it most likely won’t be soon.
I would probably fork into something like SmartBone 2 - Simulated Physics and Collision solution for Bones - Resources / Community Resources - Developer Forum | Roblox
I’ll be taking a deeper diver into this module. It basically works with a meshpart, that has an attribute called Smartbone and an armature of bones inside the part. I think ragdolling would be a simple implementation since it is designed for physics. I’ve been considering a hair physics and cape physics solution using the templates provided by that resource.
I haven’t tested this module with these Motor 6D jointed animals but I understand that it should be compatible with custom Motor6D rigs. This module is a great contribution! Good work!
Am working on hair library currently, and maybe experimenting with ragdoll physics for bones with it later.
I’ve been trying to implement this into my game for a bit of fun, and its a bit of a challenge. For one, it seems that the system clones the entire character and makes the new one invisible, which is fine, except that I have some custom nametags that I can’t get off of the clones. Is there some way to filter these out of the clone?
Second, i’ve noticed that in the game the clones get a ForceField, which doesn’t happen in my testing place with the same exact scripts. Remembered I could just remove the ForceField duration on the spawns
The purpose of the clone is to be prevent the character from teleporting on other clients than the network owner when ragdolling (the original character still teleports but this is a visual fix). The teleporting happens because, for some reason, the physics of the character pause for a while on other clients when ragdolling. The clone is made visible when ragolling and it is moved during this physics pause and when the physics start working again, the clone is made invisible. There may be a better solution to the problem but I don’t know what that would be.
You can get rid of the clone entirely by setting doChoppinessFix to false in the settings of RagdollRootConstraint in character settings. Now that you mentioned this problem, I also added a ChoppinessFixCloneCreated event property to RagdollRootConstraint objects and a getRagdollConstraintsOfGivenType method to RagdollStructure objects so that it’s possible to easily modify the clone if you want to keep it. Here’s some example code.
local RagdollSystem = require(--[[Path to RagdollSystem package]].RagdollSystem)
local RagdollStructureCollections = RagdollSystem.RagdollStructureCollections
local RagdollConstraintType = RagdollSystem.RagdollConstraintType
local ragdollStructure = RagdollStructureCollections.getRagdollStructureFromInstance(--[[character here]])
local rootConstraint = ragdollStructure:getRagdollConstraintsOfGivenType(RagdollConstraintType.builtInTypes.RagdollRootConstraint)[1]
local cloneCreatedConnection = rootConstraint.ChoppinessFixCloneCreated:Connect(function(rootConstraint, newClone)
-- do modification
end)
I’ve been using your ragdoll system for a while and I’ve run into an issue with ragdoll characters that are missing a limb. Character with their foots missing causes the module to spring an error. I don’t understand how it works because there are 30 different modules and everything is in a convoluted stack that just returns and error if something doesn’t work. I also had to implement a fix because it keeps bugging out with accessories. (removed all accessories then put them back on)
05:45:57.194 ReplicatedStorage.GeneralUtilityPackage.Characters.CharacterState.CharacterChecks:146: attempt to index nil with 'RightAnkleRigAttachment' - Server - Script:47
Why can’t it just work and skip limbs that do not exist instead of doings it thing and still springing an error because I fixed the stack error and then it says invalid character settings. This code man
Characters with RagdollRigType.R15 or RagdollRigType.R6 need to have all bodyparts. The automatic ragdoll structure creation code can only be used for such characters. My code for making layered clothing look sensible after detaching bodyparts creates the layered clothing fix parts by creating clones of the original bodyparts so I don’t know how I should add support for creating initial layered clothing fix parts for a character that is initially missing bodyparts. I guess I could use InsertService or store some default caged meshes for such cases but neither of these feels elegant.
Also, another slight problem is that although I change the size of the layered clothing fix parts, the size of the one directly connected to a non-missing bodypart still partially depends on the size of the detached bodypart and if there’s no detached bodypart then there’s no reference part for the size and using my default Vector3.new(0.1, 0.1, 0.1) size gives a slightly different visual result than having the size partially depend on the detached part’s size.
You can create a RagdollStructure for a character with missing bodyparts by calling RagdollStructure.createStructure directly and providing character settings where rig type is RagdollRigType.Custom (do this before you call any stun function). However, for characters with RagdollRigType.Custom, my code for fixing clothing when detaching bodyparts will not be run.
I haven’t noticed problems with accessories. What kind of problems are you having with them? Errors?
Part of my issue was caused by not initializing the module properly because I changed some things around. I made modifications to the ragdoll ease of use module and was able to fix the other issues i was having.
function RagdollEaseOfUse.stunCharacter(characterOrPlayer: Model | Player)
local accessories={}
local touch={}
--causes error if rig contains accessories not connected to character
if characterOrPlayer.Head:FindFirstChild("Mesh") then
if characterOrPlayer.Head:FindFirstChild("Mesh"):FindFirstChild("Settings") then
characterOrPlayer.Head:FindFirstChild("Mesh"):FindFirstChild("Settings"):Destroy()
end
end
--don't make extra joints for accessories
for i,v in characterOrPlayer:GetChildren() do
if v:IsA("Accessory") then
v.Parent=workspace
table.insert(accessories,v)
elseif v:IsA("BasePart") and v.CanTouch then
v.CanTouch=false
table.insert(touch,v)
end
end
--pcall(function()
local result= doSomethingNowOrCreateRagdollStructureWhenCharacterExistsAndIsReadyAndDoItThen(
characterOrPlayer,
function(ragdollStructure)
ragdollStructure:stunIfNotStunned()
end
)
--end)
for i,v in touch do
v.CanTouch=true
end
for i,v in accessories do
v.Parent=characterOrPlayer
end
return result
end
Currently I’m using rope constraints making skeletons that are ragdolls chained to a wall for a horror game.
The main issue I’m having is that when the model joints exceed a velocity threshold they seperate and spring back together. I experience this issue often . Do you know what will fix it? When body part collisions are disabled they do not experience this issue.
Do not use this module it is designed to not work.
A main issue I’m having I realized I wasn’t using your ragdoll for players because it doesn’t work.
It just says RagdollStructure for this character doesn’t exist and the character is not yet ready for RagdollStructure creation. (x42) - Server - RagdollEaseOfUse:70
It’s just a regular character… It works with non player characters.
I set it up like this IDK if the script is not registering new characters properly
This is the test snippet for the client sided script as well as a handler for the ragdoll signal.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RagdollSystem = require(ReplicatedStorage.RagdollSystemPackage.RagdollSystem)
local RagdollDefaultRemoteEventSystemClientUtility = RagdollSystem .RagdollDefaultRemoteEventSystemClientUtility
print("Active")
RagdollSystem.initialize()
RagdollDefaultRemoteEventSystemClientUtility.setUpServerClientCommunicationOnClient()
local Ragdoll = RagdollSystem.RagdollEaseOfUse
game.Players.LocalPlayer.CharacterAdded:Connect(function()
local c=nil
c=game.Players.LocalPlayer.PlayerGui.ragdoll.variables.ragdolltrigger:GetPropertyChangedSignal("Value"):connect(function()
if game.Players.LocalPlayer.PlayerGui.ragdoll.variables.ragdolltrigger.Value==true then
Ragdoll.stunCharacter(game.Players.LocalPlayer.Character)
else
Ragdoll.unstunCharacter(game.Players.LocalPlayer.Character)
end
end)
local dis=nil
dis=game.Players.LocalPlayer.CharacterRemoving:Once(function()
c:Disconnect()
dis:Disconnect()
end)
end)
This is my server side code.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RagdollSystem = require(ReplicatedStorage.RagdollSystemPackage.RagdollSystem)
local RagdollDefaultRemoteEventSystemServerUtility = RagdollSystem .RagdollDefaultRemoteEventSystemServerUtility
RagdollSystem.initialize()
RagdollDefaultRemoteEventSystemServerUtility.setUpServerClientCommunicationOnServer()
This ragdoll system has given me nothing but headaches and the way it is coded is honestly frustrating and incomprehensible to understand how to debug it. Why can’t it just work. It blows my mind someone would code like this. Please fix your module properly and stop skipping over issues and returning an error.
I’ll be finding a different ragdoll module that is actually designed to work without it being loaded with bloat ware and from a developer who doesn’t code like he’s building a wall to keep everyone out. Literally you designed it to not work. real nice
function RagdollValidationOfDataFromUserDefinedFunctions.validateBodypartInstancesGivenByUserDefinedFunction(bodypartInstances: {BasePart | Model | Folder}, instanceHierarchyTopInstance: Model, ragdollCharacterSettings)
local functionForGettingInstancesToIgnore = RagdollSettingsUtility.getSettingFromEitherCharacterSettingsOrSystemSettings("functionToGetInitialInstancesToIgnoreForBodypartInstance", ragdollCharacterSettings, NetworkEnvironmentAccessibilityType.shared)
if #bodypartInstances == 0 then
error("no bodypart instances")
end
for _, bodypartInstance in bodypartInstances do
if typeof(bodypartInstance) ~= "Instance" or (not bodypartInstance:IsA("BasePart") and not bodypartInstance:IsA("Model") and not bodypartInstance:IsA("Folder")) then
error("Invalid bodypart instance")
end
-- I use :IsAncestorOf instead of IsDescendantOf here so that I get an error if bodypartInstance is somehow nil.
-- If I used bodypartInstance:isDescendantOf(instanceHierarchyTopInstance), it would return true
-- and thus the code would think that everything is fine.
if not instanceHierarchyTopInstance:IsAncestorOf(bodypartInstance) then
error("All bodypart instances must be descendants of instance hierarchy top instance.")
end
for _, otherBodypartInstance in bodypartInstances do
-- no need to skip iteration when otherBodypartInstance == bodypartInstance
-- because otherBodypartInstance:IsDescendantOf(bodypartInstance) will return false in that case.
if otherBodypartInstance:IsDescendantOf(bodypartInstance) then
error("Bodypart instances must not be descendants of each other.")
end
end
for _, descendant in bodypartInstance:GetDescendants() do
if not descendant:IsA("Motor6D") or (functionForGettingInstancesToIgnore ~= nil and table.find(functionForGettingInstancesToIgnore(bodypartInstance), descendant) ~= nil) then
continue
end
local part0: BasePart, part1: BasePart = descendant.Part0, descendant.Part1
if part0 == nil and part1 == nil then
error("Both Part0 and Part1 of Motor6D are nil.")
end
-- I use isAncestorOf instead of isDescenantOf so that I don't need to check whether the possible
-- descendant (part0 or part1) is nil.
if bodypartInstance ~= part0 and not bodypartInstance:IsAncestorOf(part0) and bodypartInstance ~= part1 and not bodypartInstance:IsAncestorOf(part1) then
error(string.format("Neither part0 nor part1 is this bodypartInstance or a descendant of this bodypartInstance. bodypartInstance: %s; part0: %s; part1: %s", tostring(bodypartInstance), tostring(part0), tostring(part1)))
end
if (bodypartInstance == part0 or bodypartInstance:IsAncestorOf(part0)) and (bodypartInstance == part1 or bodypartInstance:IsAncestorOf(part1)) then
error("Both part0 and part1 are either this bodypartInstance or descendants of this bodypartInstance.")
end
local partNotInThisBodypart = if bodypartInstance == part0 or bodypartInstance:IsAncestorOf(part0) then part1 else part0
if partNotInThisBodypart ~= nil then
local isAnotherBodypartInstanceAncestorOfOrEqualToPartNotInThisBodypart = false
for _, otherBodypartInstance in bodypartInstances do
-- no need to skip iteration when otherBodypartInstance == bodypartInstance
-- because both the condition otherBodypartInstance == partNotInThisBodypart and the condition
-- otherBodypartInstance:IsAncestorOf(partNotInThisBodypart) will be false in that case.
if otherBodypartInstance == partNotInThisBodypart or otherBodypartInstance:IsAncestorOf(partNotInThisBodypart) then
isAnotherBodypartInstanceAncestorOfOrEqualToPartNotInThisBodypart = true
break
end
end
if not isAnotherBodypartInstanceAncestorOfOrEqualToPartNotInThisBodypart then
error("Found Part0 or Part1 that is not a descendant of any bodypart instance.")
end
end
end
end
end
POV let’s make a function to throw an error instead of correcting the error. It doesn’t matter if it actually matters! Throw an error anyway!
-- R6 and R15 only?
if ragdollCharacterSettings.rigType ~= RagdollRigType.Custom then
-- This code creates RigidConstraints for accessories because reparenting bodyparts sometimes destroys AccessoryWelds for some reason.
-- Also, WeldConstraints don't work because their enabled property gets set to false for some reason. That's why I used
-- RigidConstraints instead.
for _, descendant in ragdollStructure.InstanceHierarchyTopInstance:getDescendants() do
if descendant.ClassName == "Accessory" then
local handle = descendant:FindFirstChild("Handle")
if handle == nil then
error("Accessory is missing Handle.")
end
--[[
local accessoryWeld = handle:FindFirstChild("AccessoryWeld")
if accessoryWeld == nil then
error("Accessory Handle is missing AccessoryWeld. Accessory instance name: " .. descendant.Name)
end
--]]
local handleJoints = handle:getJoints()
local weld, bodypartBasePart
for _, joint in handleJoints do
if joint.ClassName == "Weld" then
weld = joint
bodypartBasePart = if weld.Part0 == handle then weld.Part1 else weld.Part0
end
end
if weld == nil then
error(`Weld missing. Accessory: {descendant:GetFullName()}`)
end
if not AccessoryUtility.isLayeredClothingInstance(descendant) then
--print(descendant.Name .. "is not a layered clothing instance.")
--accessoryWeld.Enabled = false
end
The automatic RagdollStructure creation that happens when something like RagdollEaseOfUse.stunCharacter is called for a player character indeed didn’t apparently work on the client because it’s scheduled using my own event that used to only fire after Player.CharacterAppearanceLoaded fires and some other requirements are met. Player.CharacterAppearanceLoaded never fires on the client so my custom event used to never fire on the client. I hadn’t thought of that.
Roblox fires Player.CharacterAdded and Player.CharacterAppearanceLoaded before than some of the initialization of the character has been done. For example, parenting to WorkSpace happens after these events, and setting network ownership of a player character to the player happens after parenting to workspace. I wanted an event that fires when the character is (hopefully, at least) fully initialized by Roblox which is why I made this event.
I’ve now edited the code (I’ve edited both RagdollSystem and GeneralUtility) such that on the client, the code for firing the custom event uses CharacterAdded instead of CharacterAppearanceLoaded. On the server it still uses CharacterAppearanceLoaded because I think it’s more reliable. So now the automatic RagdollStructure creation happens on the client too.
Many of the intentionally given errors are related to things that I consider reasonable requirements for the character or part of character that the RagdollStructure is being created for. Perhaps some of them are unnecessary, though.
And, unfortunately, I don’t have a solution for the joint problem you mentioned in your earlier reply (and I’m not sure if I understood if correctly).
And yes, I admit that it’s difficult for a user of RagdollSystem to debug problems with it, and that my documentation for it is somewhat insufficient. It probably is indeed better that you use another ragdoll module since mine doesn’t seem to satisfy your needs.
I couldn’t use your ragdoll system on the client period. I hope your update resolved the issue. It was pretty fruitless to try to figure out why it wasn’t working so I’m glad to hear it was an actual bug and not intended.
Surprised no one else had mentioned it.
It still blows my mind you would have your code throw an error for a weld that does not have a part1 or part0, OR an accessory missing a handle. Just skip over those things why does it matter? Not that I’ve even ran into those specific issues.
My hacked fix for skipping over accessories is working. By simply forcing the system to ignore accessories by removing them all and putting them back in afterwards.