Ragdoll Physics à la Goonya Fighter
An example of how it is possible to construct ragdoll physics with unity
Moving a character from A to B in Unity is not as straightforward as one imagines it to be. It depends on a basic understanding of vector math and physics, as well as knowing some basics about Unity operations, such as that Unity doesn’t allow direct manipulation of position variables.
thisCharacter.x += 20.0f gets you an error.
In Goonya Fighter, we went one step further – moving from A to B in a goonya-goonya (or in English, flippy-floppy) fashion, akin to a ragdoll, perched as if we could fall over at any moment. We couldn’t however go down the typical route of creating animation in software (such as Maya) and import it into Unity pre-made. Time constraints were upon us, so we had to devise another way of achieving our ragdoll effect. This post focuses on how we achieved that movement.
(Note: This article assumes that you are somewhat familiar with Unity’s animator and animation tools).
This is our skeleton, so to speak. As well as having the mesh (or character skin), it consists of various blocks to represent the limbs and more, alongside various rigidbodies, a smattering of colliders, and joint components to connect the blocks together. All of this is bundled into a prefab.
Unity presents us with 5 possible joint types to connect two blocks/objects/rigidbodies together. An overview of the various joints is below:
Hinge joint: A joint that acts like a hinge, in that it connects two objects together but allows movement of one object.
Requires: rigidbody components on both objects; numerical data to specify along which axis the movement will take place; a drag-and-dropped reference in the editor, signaling which object is the non-moving “base” so to speak (without this, the moving object hooks onto the world).
Fixed joint: a joint to fix two bodies together permanently.
Requires: rigidbody components on both bodies.
Spring joint: A joint that connects two bodies, but like a bedspring, will attempt to return the two bodies to a default distance.
Requires: Drag-and-drop reference to the “base” body (like with Hinge joints); minimum and maximum distance values between which the spring does not act (thus allowing for some freedom of movement).
Character joint: A ball-socket joint for ragdoll effects.
Requires: rigidbodies on the connected object(s); numerical data to specify along which axis the movement will take place.
Configurable joint: A joint type that basically amalgamates the function of all the other joints to give you greater flexibility and control over movement. Can use quaternions to achieve smoother rotations.
Requires: rigidbodies on the connected object(s).
Although character joints would have allowed us to attain our goals, we opted for hinge joints, as that was being used in our reference material.
We proceeded to link up the various parts of the body. Each character prefab came with a “character_reference” object, from which a list of various body parts sprouted. The hips were at the top of this hierarchy, and to this was attached the spine and left/right thighs. Items like chest/shoulders/arms/hands or upper-legs/shins/feet followed on in succession. A rigidbody was attached to each body part that was expected to rotate, move or register collisions (eg. the feet, for detecting when a kick made contact). Any two objects that were neighbouring each other in the chain and had a rigidbody attached were then given an additional hinge joint to connect them up.
For each hinge joint, we defined the Anchor as (0,0,0) (local position, not world), so that the moving object and where it swings were central to its parent object. The Axis values depended on the limb in question. The upper leg rotates up-and-down on the x rotation-axis (ie. 1,0,0), but the spine rotates round left-to-right on the y rotation-axis (ie. 0,1,0). The hips rotate on both, so they are (1,1,0). Rather than dealing with degrees, these fields can be seen as bools, with 1 being active and 0 being inactive or ignored.
The main animation came from the use of the “UseSpring” function, which opens up options to force the rigidbody to act like a hinge and rotate to a designated angle after movement is initiated; the Unity documentation says “Spring makes the Rigidbody reach for a specific angle compared to its connected body”. First, different limbs were saddled with different Spring values, depending on how much force and snapback/rebound we wanted to exert on them. Then we created animation clips that manipulated the values of Target Position variable, which pulls the object on its hinge to a certain angle before rotating the other way. We rotated the characters’ various body parts at right angles, and after experimenting, we found that for us, having the Target Position values go from 0 to -90 and back worked best. In addition, we edited our animation clip so that first one arm would perform the rotation, return, then the other arm would perform the rotation and return, so as to achieve a disjointed effect. With the Anchor and Axis values being all based on local position, we didn’t have to worry about which way our fighters were facing, whether it was left, right, up or down. Everything rotated in relation to their connecting objects.
Following this method, there was no real need to edit to a deep extent. Experimenting with different values helped us achieve the desired “ragdoll” effect that became Goonya Fighter’s trademark style. After all, legs can only go so high, and we’re not looking to recreate the splits! However flow is important to consider. Jerky movements are more likely to appear robotic than ragdoll, so transitions should not only be smooth but appear smooth. Ultimately, it has to look ragdoll, whether or not it technically is.
Once the animations were complete, we turned to the code. Animation calls were grouped into a function called AnimationProcedures() that was part of a base character class. Among a bunch of other necessary commands, button input was gathered, what type of move was ascertained, then SetTrigger(ANIMATION_NAME) was executed, signaling that the needed condition was met for the animator to launch the animation clip.
//Punch Animation if (InputInfo.isPunch && !IsGuard && !IsPunch && !IsKick && IsDropKick) { ... isPunch = true; mAnimator.SetTrigger(PUNCH_ANIMATION); ... } //KickAnimation if (InputInfo.isKick && !IsGuard && !IsPunch && !IsKick && IsDropKick) { ... isKick = true; mAnimator.SetTrigger(KICK_ANIMATION); ... }
If the command to walk was entered, then Rigidbody.AddForce was added on top of the animation call.
Then as the animation is launched, the limbs are pushed, the connected limbs react, their connected limbs react, and a ragdoll effect is achieved.
For more info on joints and how to use them, Youtube houses a wide range of tutorials to help you create the ragdoll effect that you want.
Goonya Fighter (2019) is a multiplayer party fighting game for the Nintendo Switch, developed and published by MUTAN Inc. in Tokyo. Find out more about us on twitter at @GoonyaFighterEN.
Read more about:
BlogsAbout the Author
You May Also Like