Merry christmas, everyone ! Here’s my gift to you.
I know there are many ragdoll modules already published on the devforum. However, they seem to have limitations. Many are designed specifically for R15 or R6. Some only support ragdolling on death. Also, I don’t remember seeing any of them mention being able to put only specific joints into ragdoll state. Additionally, I think that the possibility to detach limbs and have the detached limb in ragdoll state is a nice thing to have and I don’t think I’ve seen any ragdoll system post mention this kind of feature.
I decided that I want to make a ragdoll system that gives a lot of freedom while still being easy to use. If all you want is an ability to unragdoll and ragdoll an entire R15 or R6 character, with the built-in settings, doing so is as simple as calling a method in a module script. However, there’s more that this system can do.
Here are links to RagdollSystem and the other two packages/models that it needs.
RagdollSystem - Creator Marketplace
GeneralUtility - Creator Marketplace
RemoteEventSystem - Creator Marketplace
Video
The chat commands in the video are not included in the ragdoll system.
General information
Character structure requirements
Firstly, I wanted this to work with many kinds of characters. Here are the requirements:
- The bodypart connection structure must not contain cyclic connections. This requirements allows it to be represented as a tree which means that every bodypart will have clearly defined descendant bodyparts and ancestor bodyparts.
- Each bodypart can be either one BasePart, a Model or a Folder containing BaseParts.
- Different bodyparts must be connected to each other using Motor6Ds. For each Motor6D connecting two bodyparts, there must also be a rig attachment (name must be equal to
Motor6D.Name .. "RigAttachment"
) in each of the two connected bodyparts. The CFrame of the RigAttachment must be (approximately) equal to either C0 or C1 of the Motor6D depending on whether Part0 or Part1 of the Motor6D is in the same Bodypart as the rig attachment. - It’s recommended and may even be a requirement in the future that the Baseparts in a bodypart form a single assembly. I recommend using WeldConstraints for attaching BaseParts in the same Bodypart to each other. If there are Motor6Ds connecting parts in the same bodypart, you must tell the ragdoll system that these Motor6Ds should be ignored (more about this in the documentation of RagdollBodypartNode and system shared settings).
Here are some things that are not required:
- Humanoid
- HumanoidRootPart
Objects and data structures
The main class in this RagdollSystem is RagdollStructure. It contains data for a single mechanism of connected bodyparts (a character for example). Such a mechanism must have a top instance that is a Model. For each bodypart, there’s a RagdollBodypartNode object. For each RigAttachment, there’s a RagdollHalfJointNode object.
There are two hierarchies for both RagdollBodypartNodes and RagdollHalfJointNodes. These are paralyze hierarchy and break hierarchy. Each BodypartNode and HalfJointNode contains two hierarchy spesific “component” nodes, one for each hierarchy. In this system, ragdolling a whole RagdollStructure is called stunning and ragdolling spesific joints is called paralyzing. Paralyze hierarchy is used for deciding which other joints to paralyze when the user paralyzes or breaks a joint. Breakhierarchy is used for deciding which Bodyparts are moved to a new RagdollStructure when a joint is broken. There can only be one root node for bodypart hierarchies. However, because the root node of a bodypart hierarchy may be attached to multiple other bodyparts, the half joint hierarchy can have multiple root nodes and is thus represented with a forest data structure.
For each joint, a RagdollConstraint lua object is created. It is created for the HalfJointNode that is in the bodypart that contains the Motor6D. There are a few built-in RagdollConstraint classes that all inherit the base class RagdollConstraint. You can also define your own classes that inherit RagdollConstraint. For every intact joint, there’s also a RagdollIntactJoint object.
Settings
The ragdoll system uses four types of settings: character settings, system server settings, system shared settings and system client settings. It has built in R15 and R6 character settings, and all three system settings. If the characters in your game are R15 or R6 and you are fine with all the behavior and joint rotation limits chosen in the built-in settings, you don’t have to do any settings changes. However, if you want to change something, you can apply your own settings for whatever settings type needs non-default settings. Applying your own settings is meant to be done by calling functions made for this purpose in settings related module scripts instead of editing the built-in settings modules.
In the settings, you can toggle some features and define functions for many things like finding bodypart top instances in a character, instances (like Motor6Ds) that should be ignored in a bodypart or collision BaseParts of a Bodypart. Many of these functions are optional to define. There’s default code for finding bodypart top instances and collision parts. The possibility to define your own functions for these is meant for situations where the default code doesn’t work. In character settings, you can define which ragdoll constraints are used and the rotation limits.
RagdollStructure creation
With the default settings, a RagdollStructure is created for every player character when the character is considered to be fully loaded. The code for detecting when an R15 or R6 character is fully loaded is in a different Package that the RagdollSystem uses (and that package is also made by me). The function that user code should use for creating a new RagdollStructure is the createStructure function in the RagdollStructure module.
Ragdolling and breaking joints
You can ragdoll a whole character or only some joints. As mentioned before in the post, ragdolling a whole RagdollStructure is called stunning and ragdolling spesific joints is called paralyzing. By default, when paralyzing or breaking a joint, its paralyze hierarchy descendants are paralyzed as well. You can opt out of this, though. If you paralyze some joints, stun a character and unstun it, the paralyzed joints stay paralyzed. This allows using stun for temporary ragdolling that could be caused by a hit in the head, for example, and paralyze for permanent ragdolling of spesific parts as a result of weapon damage, for example.
This system never destroys Motor6Ds. Instead, it sets the Enabled property to false. By default, if the character has a humanoid, the RagdollSystem changes the humanoid state in some situations such as when the character is stunned. There is, however, a character setting for disabling this automatic humanoid state changing.
I tried to make Layered clothing look reasonable good after breaking a joint. However, the look is far from perfect and how good it looks depends on the clothing. Also, I did this using a hacky, inefficient way which involves creating as many extra parts as there are bodyparts in an R15 character.
User-defined data
Each RagdollStructure, RagdollBodypartNode, RagdollHalfJointNode and RagdollIntactJoint has a UserDefinedData property. You are free to choose what data, if any, you store in this property. It could contain some kind of a character type, for example.
Server and client
A RagdollStructure can be created either on the server or on a client. Client-only RagdollStructures should be used in cases where you create a character on the client (in which case it only exists on the client).
It is possible to replicate RagdollStructures created on the server to clients. If you opt out of some automatic bahavior, you also get to decide which clients the RagdollStructures are replicated to. It is also possible to replicate UserDefined data but that isn’t entirely automatically handled. The user of the system needs to do some things related to this. The reason why I didn’t even try to make this entirely automatic is that someone may have a table with multiple things as user-defined data and the data may include lua objects with metatables. Thus, a generalized approach wouldn’t work in all cases, only in simple ones.
With the default settings, in addition to RagdollStructures being created for every player, these RagdollStructures are replicated to every player.
The way replication works is that the client creates a copy of the RagdollStructure object and updates this copy when the server informs the client about changes. Instances are used by the RagdollSystem for getting the correct copy on the other side of the network. Instance → lua object dictionaries are used for this. I could alternatively have an id number for each lua object that can be replicated but I found using instances to be sufficient in this case.
By default, the RagdollSystem uses my RemoteEventSystem for creating, firing and listening to RemoteEvents. If you are fine with this, all you need to do is call a function that tells the system to initialize the communication using this system. However, because different people may prefer different ways of handling remote event traffic and may also want to have controll over or monitor the remote event traffic of this RagdollSystem, the Ragdoll system also allows using some other system. You just need to define some middle-man code for communicating between the RagdollSystem and the chosen Remote event code. Also, my RemoteEvent system is kind of a mess with some features that I’ve later considered bad ideas which is also a reason why I don’t want the RagdollSystem to be tightly tied to it.
The RagdollSystem has no client → server communication other than a little in initializing the communication when using the default RemoteEventSystem. All other communication is server → client. For a RagdollStructure that exists on the server, any functions that modify it (like stunning and paralyzing) should always be called on the server. Also, I’m not planning to make a feature that would bind a spesific key to telling the server to ragdoll the player’s character or any other similar feature where the client requests a change. I want to leave user input handling and client request validation to the user of the ragdoll system. These can be very game-spesific and not all games with ragdolls allow the player to decide when they want to ragdoll or unragdoll.
Other
There are methods for anchoring or unanchoring a RagdollStructure, and a method for both anchoring and disabling collisions with other parts which practically makes the ragdoll purely visual. The way anchoring the structure works is that one BasePart is anchored and the others are rigidly attached to it using WeldConstraints.
RagdollSystem uses two other packages that I’ve made. These are my GeneralUtility package and my RemoteEventSystem package. You need to have these as siblings of the RagdollSystem package. The purpose of not including them as nested packages is that ideally, only one copy of each package should be used in a game even if RagdollSystem code is not the only code using the other two packages. Having RagdollSystem actually use RemoteEventSystem is optional. You can alternatively have RagdollSystem use some other code for handling remote events. However, at least at the moment, having RemoteEventSystem as a sibling is necessary regardless.
Modules
Modules, functions/methods, properties or fields that are not documented here are not meant to be used by the user of this RagdollSystem unless I’ve just forgotten to include them. Static methods are called with dot syntax.
Field and property explanation
With “field” I mean a regular key value pair with a string key. With “property” I mean something that is read and set with the same kind of syntax as a regular key value pair but actually has a getter and a setter that are called automatically. I use camelCase for fields and PascalCase for properties (and some of my CustomEnumItems also use PascalCase while most use camelCase which is inconsistent).
Modules that contain references to other modules:
RagdollSystem
This is the main module of the RagdollSystem. This is the only module that the user of the system is supposed to directly require. You can get references to the return values (classes, CustomEnums or tables with utility functions) of other modules that are meant to be accessed by the user by indexing the table returned by this module, or the table returned by one of the modules that this module’s table gives a reference to. The references to other modules’ return values:
RagdollStructure
RagdollStructureCollections
RagdollBodypartNodeCollection
RagdollBuiltInConstraintClasses
RagdollSystemServerSettingsHandler -- server only
RagdollSystemClientSettingsHandler -- client only
RagdollSystemSharedSettingsHandler
RagdollCharacterSettingsHandler
RagdollEaseOfUse
RagdollDefaultRemoteEventSystemServerUtility -- server only
RagdollDefaultRemoteEventSystemClientUtility -- client only
RagdollEnums
RagdollEnums
This module contains references to different CustomEnums of the RagdollSystem.
RagdollBodypartCanCollideState
RagdollBodypartHumanoidRootPartConnectionState
JointParalyzeState
JointBreakState
RagdollRigType
RagdollHierarchyType
RagdollBuiltInConstraintClasses
This module contains references to built in joint constraint classes.
Base classes
ragdollBuiltInConstraintClasses.baseClasses
This table contains constraint classes that aren’t functional by themselves. They contain only some of the functionality needed. These can (and RagdollConstraint should) be inherited by other constraint classes. Base classes:
ragdollBuiltInConstraintClasses.baseClasses.RagdollConstaint
ragdollBuiltInConstraintClasses.baseClasses.RagdollOrientedConstraint -- this inherits RagdollConstraint
Derived classes
ragdollBuiltInConstraintClasses.derivedClasses
This table contains constraint classes that are fully functional. They inherit RagdollConstraint either directly or by inheriting RagdollOrientedConstraint which inherits RagdollConstraint. Derived classes:
ragdollBuiltInConstraintClasses.derivedClasses.RagdollNeckConstraint
ragdollBuiltInConstraintClasses.derivedClasses.RagdollNeckConstraintV2
ragdollBuiltInConstraintClasses.derivedClasses.RagdollBallSocketConstraint
ragdollBuiltInConstraintClasses.derivedClasses.RagdollRootConstraint
Classes:
RagdollStructure
This contains the RagdollStructure class which represents a mechanism consisting of one or more bodyparts that are attached to each other.
Constructor
createStructure(characterOrOtherTopInstance: Model | Folder, ragdollCharacterSettings, dataNeededToGetRagdollCharacterSettingsTableOnClient)
- characterOrOtherTopInstance is an instance that contains all instances that belong to the mechanism for which the RagdollStructure is created (for example Player.Character).
- ragdollCharacterSettings must be either a valid character settings table, or in case of R6 or R15, it can be nil in which case default character settings are used.
- dataNeededToGetRagdollCharacterSettingsTableOnClient can be any data that the client can use to get the client copy of the character settings table. You must define a client function that gives the settings table given this data. The table itself can’t be passed directly to the client via a RemoteEvent because it contains functions. If you aren’t replicating the structure to clients, this doesn’t need to be given. Also, if you don’t give ragdollCharacterSettings, don’t give this either.
Object methods
Life cycle
informThatUserInitializationIsDone()
There are events (a static one and an object spesific one) that are fired when this is called. Your other code can listen to either of these events. This can be useful if you need to do some additional initialization to the structure after calling RagdollStructure:createStructure and your other code shouldn’t mess with this structure before the initialization is done. This additional initialization can be setting UserDefinedData, for example.
Replication
replicateToClient()
This sends the client data containing information about the bodyparts in the RagdollStructure and the state of the structure. The client uses this data to create its own copy of the RagdollStructure object.
replicateToAllClients()
This replicated the structure to clients currently on the server and clients that join later.
informClientsAboutUserDefinedDataChange(dataNeededToUpdateUserDefinedDataOnClient)
When you change the userDefinedData on the server and want to replicate the change, call this. A few different classes have this same method but they all actually have a userDefinedData component object whose method they call so the code of the method isn’t duplicated.
- dataNeededToUpdateUserDefinedDataOnClient must be something that can be sent via a RemoteEvent
Checks
hasExactlyOneJointWithThisName(jointName: string)
containsBodypartHighestInHierarchyOfWholeCharacter(hierarchyType)
- hierarchyType must be a RagdollHierarchyType CustomEnumItem.
areChangesInThisStructureControlledByThisEnvironment
Tells whether this network environment (server or a spesific client) is the one that has authority over changes in the structure. For a structure that exists on the server, this is true on the server and false on the clients. For a client-only structure, this is true on the client.
Getters
getBrokenJointHalfJoints()
getHalfJointFromRigAttachment(rigAttachment: Attachment)
getHalfJointFromMotor6D(motor6D: Motor6D)
returns the HalfJointNode of the RigAttachment that is a descendant of the bodypart instances whose descendant the Motor6D is.
getHalfJointPairBetweenTwoBodyparts(bodypartNode0, bodypartNode1, hierarchyType)
- hierarchyType must be a RagdollHierarchyType CustomEnumItem
getAllHalfJointsFromJointName(jointName: string)
getUpperHalfJointFromName(jointName: string, hierarchyType)
getHalfJointPairFromJointName(jointName: string, hierarchyType)
getAllHalfJointPairsFromJointName(jointName: string, hierarchyType)
getBodypartNodeFromName(bodypartName: string)
getAllBodypartNodesFromName(bodypartName: string)
getBodypartNodeFromInstanceInBodypart(instanceInBodypart: Instance)
getAllHalfJointPairs(hierarchyType)
getIntactJointFromMotor6D(motor6D: Motor6D)
getRootBodypartNodeFromHierarchyType(hierarchyType)
getHalfJointHierarchyForestFromHierarchyType(hierarchyType)
Stunning and unstunning
stunIfNotStunned()
unstunIfStunned()
toggleStun()
Paralyzing and unparalyzing
paralyzeHalfJoint(halfJointNode, paralyzeParams)
- paralyzeParams must contain a boolean implicitlyParalyzeParalyzeHierarchyDescendants
unparalyzeHalfJoint(halfJointNode, unparalyzeParams)
- unparalyzeParams must contain booleans implicitlyUnparalyzeParalyzeHierarchyDescendants, removeImplicitParalyzeCausedByJointBreakRegardlessOfAncestors and ignoreWhetherParentOfExplicitlyUnparalyzedNodeIsParalyzedFromExplicitParalyze
paralyzeJointBasedOnHalfJointPair(halfJointPair, paralyzeParams)
paralyzeJointBasedOnJointName(jointName: string, paralyzeParams)
unparalyzeJointBasedOnHalfJointPair(halfJointPair, unparalyzeParams)
unparalyzeJointBasedOnJointName(jointName: string, unparalyzeParams)
Breaking and merging
breakJoint(intactJoint, paralyzeParams)
breakJointCorrespondingToHalfJointPair(halfJointPair, paralyzeParams)
breakJointCorrespondingToMotor6D(motor6D: Motor6D, paralyzeParams)
breakJointBetweenTwoBodyparts(bodypartNode0, bodypartNode1, paralyzeParams)
breakJointBasedOnName(nameOfJointToBreak: string, paralyzeParams)
disableCollisionsBetweenBodypartsThatShouldNotCollideInMergedStructure(halfJointInSelf, structureToMergeToSelf)
mergeStructureThatIsLowerInHierarchyToSelf(halfJointInSelf, structureToMergeToSelf, unparalyzeParams)
Anchoring, unanchoring and completely disabling physics
getAnchoringRootBasePart()
This returns the BasePart that is anchored when the structure has been anchored using the anchor() method. The other BasePart are attached to the anchored one using WeldConstraints.
anchor()
unanchor
disablePhysicsInteraction()
This anchors the structure and makes the bodyparts non-collidable.
Physics networking
getAssemblyRootParts()
setNetworkOwner(newNetworkOwner)
Sets the network owner for every assembly that has parts as descendants of the InstanceHierarchyTopInstance of the RagdollStructure object.
- newNetworkOwner can be either a Player Instance or nil (which means server).
setNetworkOwnershipAuto()
Sets the network ownership changing behavior to the automatic engine behavior for every assembly that has parts as descendants of the InstanceHierarchyTopInstance of the RagdollStructure object.
Clean up
destroy()
This is a clean up method.
Object properties
ParalyzeBodypartHierarchyRootNode
ParalyzeHalfJointHierarchyForest
ParalyzeHalfJointHierarchyRootNodes
BreakBodypartHierarchyRootNode
BreakHalfJointHierarchyForest
BreakHalfJointHierarchyRootNodes
HumanoidRootPartNode
Humanoid
InstanceHierarchyTopInstance
IsStunned
HumanoidPhysicsEnabled
IsOutdated -- true if the structure has been destroyed or merged to a structure higher in break hierarchy
IsClientOnly
IsBeingReplicatedToAllClients
PlayersThatThisHasBeenReplicatedTo
IsBeingReplicatedToNewClients
RagdollCharacterSettings
AssemblyNetworkOwner
Name
UpdateBodypartCanCollideStatesAutomatically
MarkedAsOutdated -- an event
StunStateChanged -- an event
UserInitializationDone -- an event
BodypartsAddedOrRemoved -- an event
IsAnchored
IsUserInitializationDone
UserDefinedData
RagdollStructureNode
This is the base class of RagdollBodypartNode and RagdollHalfJointNode.
Object methods
getHierarchySpesificComponentFromHierarchyType(hierarchyType)
- hierarchyType should be a RagdollHierarchyType CustomEnumItem
informClientsAboutUserDefinedDataChange(dataNeededToUpdateUserDefinedDataOnClient)
- see documentation for the same method in RagdollStructure
Object properties
ParalyzeHierarchyComponent
BreakHierarchyComponent
UserDefinedData
IsDestroyed
RagdollBodypartNode
This is a class whose objects contain bodypart related data. This class inherits RagdollStructureNode. Check the documentation for that for the documentation of inherited methods and properties.
Static methods
areThereNoCollisionConstraintsBetweenTheseBodyparts(bodypartNode0, bodypartNode1)
createNoCollisionConstraintsBetweenBodyparts(bodypartNode0, bodypartNode1)
Each CollisionBasePart in bodypartNode0 gets a NoCollisionConstraint with each CollisionBasePart in bodypartNode1.
destroyNoCollisionConstraintsBetweenBodyparts(bodypartNode0, bodypartNode1)
Object methods
setCanCollideState(newCanCollideState)
- newCanCollideState must be a RagdollBodypartCanCollideState CustomEnumItem
updateCanCollideStateToCurrentlyCorrectOne()
getInstancesInBodypart()
getBaseParts()
addInstanceToIgnoreList(instance: Instance)
- instance should be a descendant of the top instance of the bodypart.
removeInstanceFromIgnoreList(instance: Instance)
Object properties
BodypartInstance
RagdollStructure
BodypartName
CollisionBaseParts
InstancesIgnoredByRagdollSystem
CanCollideState
RagdollHalfJointNode
This is a class whose Objects contain joint related data. These objects are not destroyed when a joint is broken. This class inherits RagdollStructureNode. Check the documentation for that for the documentation of inherited methods and properties.
Object properties
JointName
BodypartNode
IntactJoint
RigAttachment
Motor6D
RagdollConstraint
RagdollStructure
ParalyzeState
BreakState
RagdollStructureNodeHierarchySpesificComponent
This is the base class of RagdollBodypartNodeHierarchySpesificComponent and RagdollHalfJointNodeHierarchySpesificComponent. This inherits GeneralTreeDataStructureNode which is in the GeneralUtility package for which I haven’t written documentation and thus there isn’t documentation for the methods and properties inherited from that class. Some of these include object methods getRootNodeOfTree(), getAllNodesInTree(), getDescendants and getArrayOfSelfAndDescendants(), and object property Parent.
Object properties
MainNode -- a RagdollBodypartNode or a RagdollHalfJointNode
HierarchyType -- A RagdollHierarchyType CustomEnumItem
RagdollBodypartNodeHierarchySpesificComponent
This class contains hierarchy spesific data for RagdollBodypartNodes.
Object properties
HalfJointNodeHighestInHierarchy -- HalfJointNode connecting to a bodypart higher in the hierarchy (parent bodypart)
OtherHalfJoints -- HalfJointNodes connecting to bodyparts lower in the hierarchy (child bodyparts).
RagdollHalfJointNodeHierarchySpesificComponent
This class contains hierarchy spesific data for RagdollHalfJointNodes.
Object properties
HalfJointPair
IsUpperHalfJointComponent – true if this is the higher (in hierarchy) half joint in the HalfJointPair in which this object is.
RagdollIntactJoint
This is a class whose objects contain data related to an intact joint. Intact joint means that the bodyparts between which the joint is are attached. A joint that is in ragdoll state is still an intact joint because the ragdoll constraint attaches the bodyparts to each other.
Object methods
isJointParalyzed()
informClientsAboutUserDefinedDataChange(dataNeededToUpdateUserDefinedDataOnClient)
- see documentation for the same method in RagdollStructure
Object properties
ParalyzeHierarchyHalfJointPair
BreakHierarchyHalfJointPair
RagdollStructure
HalfJointWithMotor6D
HalfJointWithoutMotor6D
Motor6D
RagdollConstraint
JointName
UserDefinedData
IsDestroyed
RagdollHalfJointPair
This class contains joint related data. Some of it is hierarchy spesific. There are HalfJointPair objects for both hierarchies.
Object methods
isJointParalyzed()
isJointExplicitlyParalyzed()
This returns whether at least one of the HalfJoints has been explicitly paralyzed.
isJointBroken()
isJointControlAble()
This returns true if the joint isn’t broken or paralyzed.
isJointInNormalState()
Object properties
HierarchyType
UpperHalfJointNodeHierarchySpesificComponent
LowerHalfJointNodeHierarchySpesificComponent
UpperHalfJointNode
LowerHalfJointNode
HalfJointWithMotor6D
HalfJointWithoutMotor6D
Motor6D
RagdollConstraint
IntactJoint
RagdollStructure
JointName
RagdollBallSocketConstraint
Constructor
new
This isn’t meant to be called by the user of the RagdollSystem. Instead, it should be included in the joint settings in character settings.
RagdollNeckConstraint
Constructor
new
This isn’t meant to be called by the user of the RagdollSystem. Instead, it should be included in the joint settings in character settings.
RagdollNeckConstraintV2
Constructor
new
This isn’t meant to be called by the user of the RagdollSystem. Instead, it should be included in the joint settings in character settings.
RagdollRootConstraint
Constructor
new
This isn’t meant to be called by the user of the RagdollSystem. Instead, it should be included in the joint settings in character settings.
Object methods
recreateChoppinessFixClone()
This is related to the client-side visual fix for a problem that happens when ragdolling. The problem is that the character freezes for a bit and then teleports to where it should be. I used a client-only clone of the character for fixing this. When called on the client, that client’s clone is recreated. When called on the server, the server tells every client to whom the RagdollStructure is replicated to recreate their clone.
Settings fetching and updating
RagdollCharacterSettingsHandler
This is an utility module used for setting and fetching default character settings for R15 and R6 characters. These default settings are initially the built-in ones but you can also set your own default settings. Default settings are used when you don’t give a ragdollCharacterSettings table to RagdollStructure.createStructure(). You can’t have default settings for characters other than R15 or R6.
Functions
applyDefaultR15Settings(newDefaultR15Settings, dataNeededToGetSettingsTableOnClient)
- dataNeededToGetSettingsTableOnClient needs to be something that can be sent via a RemoteEvent. You must define a client function for getting settings given the data.
applyDefaultR6Settings(newDefaultR6Settings, dataNeededToGetSettingsTableOnClient)
getDefaultR15Settings
getDefaultR6Settings
RagdollSystemServerSettingsHandler
This is an utility module used for setting and fetching system server settings. These settings are initially the built-in ones but you can also set your own settings.
Functions
applySystemServerSettings(newServerSettings)
getSystemServerSettings()
Fields
newRagdollSystemServerSettingsApplied
RagdollSystemClientSettingsHandler
This is an utility module used for setting and fetching system client settings. These settings are initially the built-in ones but you can also set your own settings.
Functions
applySystemClientSettings(newClientSettings)
getSystemClientSettings()
Fields
newRagdollSystemClientSettingsApplied
RagdollSystemSharedSettingsHandler
This is an utility module used for setting and fetching system shared settings. These settings are initially the built-in ones but you can also set your own settings. You are meant to onlys set shared settings on the server. When they are set, the server informs the client about them changing and sends the client the data that you gave to applySystemClientSettings() so that the client can get the settings table using the function defined in system client settings.
Functions
applySystemSharedSettings(newSharedSettings, dataNeededToGetSettingsTableOnClient)
* dataNeededToGetSettingsTableOnClient must be something that can be sent via a RemoteEvent and that the function you define in system client settings can use to fetch the settings table.
getSystemSharedSettings()
Fields
newRagdollSystemSharedSettingsApplied -- an event
Default RemoteEventSystem middleman modules
RagdollDefaultRemoteEventSystemServerUtility
This is a server middle man between the RagdollSystem and my RemoteEventSystem. As mentioned earlier in the post, you can also use some other remote event code. You just have to define a function (functionToFireRemoteEvent) in the system server settings and call RagdollNewPlayerCommunicationOrderHandler.informThatClientIsReadyForReplication when the client is ready to listen for RagdollSystem remote event firings.
Functions
setUpServerClientCommunicationOnServer()
Fields
fireClient
- This is a function but I put it in the fields category because it’s not meant to be called directly from this module. It’s meant to be set as a setting in system server settings if you want the RagdollSystem to use my RemoteEventSystem.
RagdollDefaultRemoteEventSystemClientUtility
This is a client middle man between the RagdollSystem and my RemoteEventSystem. As mentioned earlier in the post, you can also use some other remote event code.
Functions
setUpServerClientCommunicationOnClient()
RemoteEvent modules not spesific to the default RemoteEventSystem
RagdollNewPlayerCommunicationOrderHandler
This is a server-only module used for starting communication with clients and specifying the order in which the client is informed about different things.
Functions
hasClientConnectedRadollSystemCodeToRagdollSystemRemoteEvents(player: Player)
getClientsWhoHaveConnectedRagdollSystemCodeToRagdollSystemRemoteEvents()
informThatClientIsReadyForReplication(player: Player)
You should only call this if you are not using my RemoteEventSystem.
Fields
playerReadyForReplication -- an event
This gives the following to connected functions:
- the Player
RagdollInternalRemoteEventsClientHandler
This is a client-only module.
Functions
handleRagdollSystemClientEvent(remoteEventPurposeValue: number, ...)
This should be called by whatever remote event system is being used. remoteEventPurposeValue
should be the number that the RagdollSystem gave to functionToFireRemoteEvent. functionToFireRemoteEvent is defined in system server settings.
Modules for ease of use of the system
RagdollStructureCollections
This is an utility module for getting already created RagdollStructures from instances and for listening to the creation of new structures or the initialization of them being completed.
Functions
getRagdollStructureFromInstance(instance: Instance)
- instance should be the InstanceHierarchyTopInstance of the RagdollStructure object or a descendant of this top instance.
getPlayerCharacterRagdollStructure(player: Player)
setPlayerCharacterRagdollStructure(player: Player, playerCharacterRagdollStructure)
If the character for which a RagdollStructure is created is Player.Character of a player, then this function is called automatically when the structure is created. But if you have a custom player character that is not Player.Character, you can call this function if you want to be able to later access the RagdollStructure using the Player instance.
getPlayerSpesificRagdollStructureCreatedEvent(player: Player)
getPlayerSpesificRagdollStructureUserInitializationDoneEvent(player: Player)
Fields
ragdollStructureCreated -- an event
This gives the following to connected functions:
- the RagdollStructure object
- the InstanceHierarchyTopInstance of the RagdollStructure object
ragdollStructureUserInitializationDone -- an event
This gives the following to connected functions:
- the RagdollStructureObject
RagdollBodypartNodeCollection
This is an utility module for getting a RagdollBodypartNode from an instance.
Functions
getBodypartNodeFromInstanceInBodypart(instanceInBodypart: Instance)
- instanceInBodypart should be either the top instance of a bodypart or a descendant of that top instance.
RagdollEaseOfUse
This is an utility module that is meant to make it easy to use this RagdollSystem for simple things.
Functions
getRagdollStructureFromCharacterOrPlayer(characterOrPlayer: Model | Player)
getLocalPlayerCharacterRagdollStructure()
stunCharacter(characterOrPlayer: Model | Player)
If the RagdollStructure doesn’t exist yet, a ragdoll structure with default character settings will be created when the character exists (if characterOrPlayer is a player) and is ready (has bodyparts that a normal R15 or R6 character should have etc.), and it will then be stunned. If the given characterOrPlayer is an NPC, it is expected to be ready when this function is called.
unstunCharacter(characterOrPlayer: Model | Player)
Similar to RagdollEaseOfUse.stunCharacter but unstuns.
toggleRagdoll(characterOrPlayer: Model | Player)
Similar to RagdollEaseOfUse.stunCharacter but toggles stun state (either stuns or unstuns).
Fields
ragdollStructureAddedForPlayerCharacter -- an event
This gives the following to connected functions:
- the RagdollStructure object
- the character Model
- the Player
ragdollStructureAddedForLocalPlayerCharacter -- a client-only event
This gives the following to connected functions:
- the RagdollStructure object
- the character Model
CustomEnums of the RagdollSystem
RagdollRigType
CustomEnumItems
R6
R15
Custom
RagdollHierarchyType
CustomEnumItems
paralyzeHierarchy
breakHierarchy
JointParalyzeState
CustomEnumItems
controlable
explicitlyParalyzed
implicitlyParalyzedFromExplicitParalyze
implicitlyParalyzedFromJointBreak
implicitlyParalyzedFromBothExplicitParalyzeAndJointBreak
explicitlyParalyzedAndImplicitlyParalyzedFromJointBreak
JointBreakState
CustomEnumItems
Intact
Broken
RagdollBodypartCanCollideState
CustomEnumItems
AllBasePartsCanCollideTrue
AllBasePartsCanCollideFalse
UpdateBasedOnHumanoidState
NotControlledByRagdollSystem
Undefined
Settings
If you aren’t happy with the built-in settings, you can define your own settings.
Info about settings that can be defined in either system or character settings
Some settings can be defined in either character or system settings (or neither if its an optional setting). If the setting is defined in both system and character settings, the value in character settings is used. The purpose of this is that, if a setting is the same for most character types in the game, you can put that setting value in system settings so you don’t need to set it to multiple character settings. If some characters need a diffrent setting value than most, you can define the setting separately for them in character settings.
Here’s what the settings tables must or can contain.
Character settings
rigType
a RagdollRigType CustomEnumItem
defaultFadeFadeTimeFromRagdollOffsetToAnimationOffset
This can alternatively be defined in system shared settings. See the documentation for system shared settings for the documentation of this.
mirrorLimitsWhenNameContainsRight
This is used when creating RagdollBallSocketConstraints. This name may be somewhat misleading. The limit properties of the BallSocketConstraint instance are not changed depending on this. Instead, the mirroring is done by changing the rotation of the Attachments (the rig attachments’ rotation isn’t altered; instead the BallSocketConstraint uses Attachments that are parented to the rig attachments).
revertRigAttachmentRotationOnRagdollConstraintAttachments
When this is true, the rotation of the Attachments of a RagdollConstraint is not affected by the rotation of the RigAttachment. (their rotation in this case is RigAttachment.CFrame.Rotation:Inverse() * definedRotationCFrame).
chooseRigAttachmentOfBodypartWithMotor6DAsRigAttachment1
This affects how a BallSocketConstraint limits the rotation.
shouldRagdollSystemChangeHumanoidState
If this is false, the RagdollSystem won’t automatically change the state of the Humanoid in the character even if the Humanoid exists.
nameOfParalyzeHierarchyRootBodypart
nameOfJointConnectingToStructureHigherInParalyzeHierarchy
This shouldn’t be defined for a whole character. It should only be defined when creating a structure that is meant to be merged to another structure, like a metal limb that can be used to replace a lost limb.
nameOfBreakHierarchyRootBodypart
nameOfJointConnectingToStructureHigherInBreakHierarchy
Same explanation as for nameOfJointConnectingToStructureHigherInParalyzeHierarchy.
jointSettings
For each joint type name (for example, the joint type name of LeftShoulder and RightShoulder is Shoulder in the default R15 settings), data for creating RagdollConstraints is defined in this table.
This should contain jointTypeName → {ragdollConstraintSettings = a table of settings} key value pairs. The table of settings should have ragdollConstraintConstructor as one of its keys and other needed key value pairs (what is needed depends on the constraint class) as the other key value pairs.
The constructor is given the following:
- joint name
- joint type RagdollConstraint settings (constructor and constraint type dependent settings)
- ragdoll character settings
- replicated instances of the RagdollConstraint if the lua object being created is a client copy.
The constraint type spesific settings are the following:
RagdollBallSocketConstraint:
- rotationAxis: a string (“X”, “-X”, “Y”, “-Y”, “Z” or “-Z”) or a vector
- secondaryAxis: a string (one of the above) or a vector
- upperAngle: an angle in degrees
- twistLowerAngle: an angle in degrees
- twistUpperAngle: an angle in degrees
- maxFrictionTorque: a number
RagdollRootConstraint:
- primaryAxis: a string (one of the above) or a vector
- secondaryAxis: a string (one of the above) or a vector
- setServerAsNetworkOwnerOnEnable: a boolean
- doChoppinessFix: a boolean
- choppinessFixInterpolationDuration: a number
RagdollNeckConstraint:
- torsoYAxisSecondary: a string (one of the above) or a vector
- headXAxisSecondary: a string (one of the above) or a vector
- headZAxisSecondary: a string (one of the above) or a vector
- torsoYAxis: an angle in degrees
- headXAxis: an angle in degrees
- headZAxis: an angle in degrees
- maxFrictionTorque: a number
RagdollNeckConstraintV2:
- maxBallSocketConstraintTwistAngle: an angle in degrees
- maxBallSocketConstraintUpperAngle: an angle in degrees
- maxFrictionTorque: a number
constraintDefaultValues
This can be used to set some default values for RagdollConstraints so that you don’t need to store everything separately for every joint. Currently, setting anything other than maxFrictionTorque here is not supported for the built-in constraint classes.
functionToGetJointTypeName
extraNoCollisionPairs
This should contain bodypart name pair arrays ({name, anotherName}) defining which bodyparts other than ones directly connected to each other should have NoCollisionConstraints between them.
functionToGetCollisionPartsFromBodypartInstance
This can be either nil or a function that returns an array of BaseParts given the top instance of a bodypart. If this is nil, any BasePart that is either the top instance of the bodypart or its descendant is considered a collision BasePart.
shouldUserDefinedDataBeReplicatedToClients
This can alternatively be defined in system server settings. See the documentation for system server settings for the documentation of this.
functionToConvertRagdollStructureUserDefinedDataToFormThatCanBeSentToClient
functionToConvertBodypartNodeUserDefinedDataToFormThatCanBeSentToClient
functionToConvertHalfJointNodeUserDefinedDataToFormThatCanBeSentToClient
functionToConvertIntactJointUserDefinedDataToFormThatCanBeSentToClient
These can alternatively be defined in system server settings. See the documentation for system server settings for the documentation of these.
functionToConstructRagdollStructureUserDefinedDataOnClient
functionToConstructBodypartNodeUserDefinedDataOnClient
functionToConstructHalfJointNodeUserDefinedDataOnClient
functionToConstructIntactJointUserDefinedDataOnClient
These can alternatively be defined in system client settings. See the documentation for system client settings for the documentation of these.
functionToUpdateRagdollStructureUserDefinedDataOnClient
functionToUpdateBodypartNodeUserDefinedDataOnClient
functionToUpdateHalfJointNodeUserDefinedDataOnClient
functionToUpdateIntactJointUserDefinedDataOnClient
These can alternatively be defined in system client settings. See the documentation for system client settings for the documentation of these.
functionToGetBodypartInstances
functionToGetInitialInstancesToIgnoreForBodypartInstance
functionToGetNewParentOfBodypartInstance
These can alternatively be defined in system shared settings. See the documentation for system shared settings for the documentation of these.
System server settings
automaticallyHandleRagdollStructureCreationReplicationAndDestructionForPlayerCharacters
When this is true, a RagdollStructure is created for a player character when GeneralUtility.Characters.CharacterState.CharacterHasEverything fires on the server. The RagdollStructure is also replicated for all players and destroyed on Player.CharacterRemoving.
shouldUserDefinedDataBeReplicatedToClients
If this is true but the functions for replicating aren’t defined, an error will be thrown.
functionToFireRemoteEvent
This function needs to take a number, a player and a variable number of other arguments. So the function definition should be something like this: function(fireTypeNum: number, player: Player, ...)
. The remote event system that is used must give this number and the … arguments to RagdollInternalRemoteEventsClientHandler.handleRagdollSystemClientEvent on the client.
functionToConvertRagdollStructureUserDefinedDataToFormThatCanBeSentToClient
functionToConvertBodypartNodeUserDefinedDataToFormThatCanBeSentToClient
functionToConvertHalfJointNodeUserDefinedDataToFormThatCanBeSentToClient
functionToConvertIntactJointUserDefinedDataToFormThatCanBeSentToClient
These only need to be defined when the user-defined data should be replicated. These should convert it to something that can be sent via a RemoteEvent. The client needs to be able to construct and set the data using the construction functions defined in system client settings or character settings given the Object whose user-defined data it is and the return value of these functions.
System client settings
choppinessFixCloneParent
This is an optional setting. It’s value must be either an Instance or nil. If it’s nil, the clone is parented to the parent of the original.
functionToGetSettingsTableUsingDataReceivedFromServer
The data is the data given to this is the data you gave to RagdollStructure.createStructure, RagdollCharacterSettingsHandler.applyDefaultR15/R6Settings or RagdollSystemSharedSettingsHandler.applySystemSharedSettings for getting the settings on the client.
functionToConstructRagdollStructureUserDefinedDataOnClient
functionToConstructBodypartNodeUserDefinedDataOnClient
functionToConstructHalfJointNodeUserDefinedDataOnClient
functionToConstructIntactJointUserDefinedDataOnClient
These functions are given the object whose UserDefinedData should be created and set, and the data that the corresponding conversion function defined in system server settings returns.
functionToUpdateRagdollStructureUserDefinedDataOnClient
functionToUpdateBodypartNodeUserDefinedDataOnClient
functionToUpdateHalfJointNodeUserDefinedDataOnClient
functionToUpdateIntactJointUserDefinedDataOnClient
These functions are given the object whose UserDefinedData should be updated, and the data that you gave to the informClientsAboutUserDefinedDataChange method of the object whose user-defined data was updated.
System shared settings
maxDistanceToBeConsideredToBeRelatedToTheSameJoint
minCorrespondingDirectionVectorDotProductToBeConsideredToBeRelatedToTheSameJoint
These are used for checking whether Motor6D C0 or C1 and rig attachment CFrame are close enough to each other.
automaticallyRagdollOnHumanoidDeath
defaultFadeFadeTimeFromRagdollOffsetToAnimationOffset
When a joint goes from ragdoll state to normal state (Motor6D is enabled), the Transform property is gradually interpolated between the ragdoll state rotation and animation rotation. This defines the time it takes for the interpolation to reach the Animation Transform. The reason I put “default” in the name was probably that I was planning to allow the user to define their own way of transitioning from ragdoll to animations. However, at least currently, such a possibility is not implemented.
functionToGetBodypartInstances
This is optional to define. If it is defined, it should return an array of bodypart top instances given the top instance of the RagdollStructure being created.
functionToGetInitialInstancesToIgnoreForBodypartInstance
This is optional to define. If it is defined, it should take a bodypart top instance and return an array of instances (descendants of the bodypart top instance) that should be ignored by the RagdollSystem.
functionToGetNewParentOfBodypartInstance
This is optional to define. If it is defined, it should return the new parent of the top instance of a bodypart given the bodypart node and the top instance of the RagdollStructure to which the bodypart was moved as a result of breaking or merging a joint.