C# Code Generator As Add-on for Unity3D Ragdoll Wizard

C# Code Generator As Add-on for Unity3D Ragdoll Wizard

Using Unity’s ragdoll wizard leads to the problem that the prefab connection to the character model is broken. That means after a change of the model in your 3D software yo have to perform the whole procedure again. To avoid this I wrote an open source code generator that saves all ragdoll components in a C# factory class which you can invoke at runtime.

NOTE: This is currently not supported on newer versions of Unity3D !

Introduction

Within games most often a character is moving without control of the physics engine (i.e. kinematic) as long as it is alive. Then when it comes to a crash you want to behave it like a rag doll under full control of the physics engine. You can easily build all joints, colliders and rigid bodies of your rigged model with Unity’s Ragdoll wizard.The result is not too bad and with a little tweaking of angles, limits, masses and whatsoever you will have a spectacular show down.

The price you pay is that your game object is disconnected from the original model as FBX import. Applying changes to your model (in my case a .blend file) will have no effect on the game object until you do a revert of it and execute the ragdoll wizard again. It appears like there is no simple solution – at least I never got an answer to my question.

So I decided to write a little code generator based on Unity’s editor classes‘ interface that creates the code of a C# code as factory class containing everything to assign the components at runtime. The basic idea is to traverse all character joints from a selected bone and generate the code for creating the joints themselves as well as the colliders and rigid bodies with all their properties. The generated class (looks similar to this sample code) is then included in the project and will be compiled like every other class. It offers a public method to be called at runtime to create the ragdoll components on the fly.

Quick Start

I assume that you have a model prefab imported as FBX from Blender, Maya, … let’s called it PlayerModel. It consists of a hierarchy of bones. The left thigh is for example PlayerModel/Armature/Hips/Thighs_L

  • Initial setup
    • Make a backup of your project / perform a commit to your repository
    • Optionally make a copy of your model, rename it and disable it. This is just for convenience especially if you are modifying the generator itself
    • Apply the ragdoll wizard to create all components – the model’s prefab connection will be broken
    • Download RagdollCodeGenerator.cs
    • Place it in a folder MyProject/Assets/Editor/ and switch back to Unity
      After a few seconds there should be a new menu item Tools/Generate Ragdoll Code. If not, restart Unity (if ever, this will be needed only the very first time)
  • Code generation
    • Select the root bone Hips
    • Execute Tools/Generate Ragdoll Code and select folder and file name (will be used as class name automatically), e.g Assets/Scripts/Player/RagdollFactoryGenerated.cs.
      The newly created file (RagdollFactoryGenerated.cs) can be found at the specified place
    • Select the model and click revert at the top of the inspector tab. This will restore the model’s prefab connection to the .FBX file
  • Code for runtime
    • In your existing source code look for an appropriate place where the collision is detected and add:

Fine-Tuning

Generation

If you don’t want to use the complete rig you can alternatively select the bones for which you like to generate code. But anyway all children are considered too. If something goes wrong, check the Unity editor log.

If you want a specific physic material to be assigned to the colliders you can put it to folder Assets/Resources. The default name is RuntimeMaterials/Physic/PlayerPhysicMaterial but can you use an arbitrary material and edit the following line inRagdollCodeGenerator.cs :

At Runtime

Whenever I integrate generated code to my projects, I use a facade for encapsulating calls to it to get more control. So I told the generator to create a class RagdollFactoryGenerated and I created a RagdollFactory manually for exclusive access to RagdollFactoryGenerated. Additionally I prefer a singleton pattern. Here is the code:

In the initialisation phase of your application just call

If you need explicit access to the generated Collider, Rigidbody or CharacrerJoint objects, this is provided by public member RagdollFactoryGenerated.allColliders, … The main use case is setting all rigid bodies‘ IsKinematic flag. Another cool scenario is adding script components to your bone objects to set up a fine grained compound collider with its own collision detection.

Additionally every created bone has a member variable assigned. Again all access to these members should be limited to the encapsulating RagdollFactory class and in this case I’d suggest giving it a more comprehensible name like PlayRagdollHandler because  its responsibility is not limited to creation process.

All generated methods are marked as virtual to enable overriding by subclasses. This is an option for further fine tuning but may be the second best choice. Always take into consideration the possibilities offered by the code generator. If something needs to be improved it might be easier to change the generator’s code and perform regeneration.

Tweaking Parameters in Editor Mode

In order to do some fine-tuning on the ragdoll components in editor mode you need to go the other way round: create all the components from source code in editor mode and apply them again to your original model. To accomplish this you find another menu item Tools/Assign Ragdoll Components. Select the model, execute and your model will have all components in editor mode (obviously this enforces losing the prefab connection temporarily).

Now you can tweak the parameters or add new ragdoll components manually. To test your changes at runtime, you should disable the call to CreateRagdollComponents. If everything works fine, perform a Tools/Generate Ragdoll Code to „bake“ your changes to RagdollFactoryGenerated.cs again and do a revert on your model to re-enable prefab connection.

Summary And Outlook

This was a quick hack. Although I think it’s not too hard to understand, it has at least the following design flaws:

  1. Blob class anti pattern: One class with 450 lines of code is too huge.
  2. No split of responsibility. Utility functions for formatting should be put in their own class. Creation of colliders, … and should rather be done in own classes.
  3. Class methods only. To get a class hierarchy like in (2), static methods need to be converted to instance member functions.

Another open issue deals with the javascript community. While the editor class might stay in C#, mixing the languages at runtime sounds like a bad idea so a 2nd interface for javascript output is needed to fit their needs.

In general code generators are powerful tools. If you are new to this topic and feel inspired to use them in your project, yes they are cool and provide sometimes elegant solutions. But I recommend alway to investigate alternative ways that are easier to go and less complex. As a rule of thumb I use them when I have no control over the source and there is a need to reflect changes. Their use is not limited to your favourite programming language. You can write SQL statements accessing DDL tables to generate other (DML) statements or you can use XSLT to generate a java class from an XML file.

Hernan, one of the users of this code generator, wrote about his experience when using ragdoll wizard and this code generator. See Unity Ragdoll and Collisions with Rigidbodies with Kinematics and Unity3d: kill a character and make him die like a ragdoll

If you are interested to enhance the above ragdoll code generator please drop a comment or contact me.

Kay

Comments are closed.

Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu Mehr
By continuing to use the site, you agree to the use of cookies. More

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close