Hair And Clothing Physics
Key Problem
UploadUsing InUnity ProgressChan’s Spring Bone doesn’t yield realistic physics especially when the hair/clothing needs to interact with other colliders
Expected Output
Hair and clothing need to be able to interact with other colliders realistically.
Possible Solution
Using built-in unity’s character joint and collider to simulate hair and clothing physics
Prerequisite
- Character needs to have colliders on his/her body parts. The easies way is using Unity’s ragdoll creator (from menu GameObject → 3D Object → Ragdoll…), and set all the rigidbodies to kinematic
- Character Animator needs to be set it’s Update Mode to Animate Physics
- Character hair needs to have bones
Adding Character Joint
- Select the hair/clothing/accessory bones that needs to be physically animated.
- Add Character Joint component and Collider (Select appropriate primitive collider, capsule works best in almost all situation)
- Set child’s Character Joint’s Connected Body to their parent’s rigidbody. The top most (in hierarchy) Character Joint Connected Body needs to be set to corresponding kinematic rigidbody (e.g. Hair Character Joint is connected to Head)
- For hair and clothing rigidbody component, set Drag to 10 and Angular Drag to 20
- Detach the Character Joints from their parent
Helper Scripts
- Detaching Character Joints from their parent can make the scene view looks unorganized. That’s why it’s best to detach them by script at runtime. Add this script to the hair/clothing gameobject with Character Joint.
using UnityEngine;
using System.Collections;
public class MoveForce : MonoBehaviour {
Rigidbody rb;
Transform me;
// Use this for initialization
IEnumerator Start () {
me = transform;
rb = GetComponent<Rigidbody>();
rb.isKinematic = true;
//Wait until animation ready
yield return null;
yield return null;
me.SetParent(null);
rb.isKinematic = false;
}
}
- Assigning Character Joint’s connectedBody manually could be a tedious task if there’s a lot of joints, use this helper script to assign them automatically, just select the top end Joint and select from the menu Character Joint → Connect Character Joint Childs
using UnityEngine;
using UnityEditor;
public class CharacterJointFiller : MonoBehaviour
{
[MenuItem("Character Joint/Connect Character Joint Childs")]
static void FillChild()
{
GameObject[] gameObjects = Selection.gameObjects;
for(int i = 0; i < gameObjects.Length; i++)
{
FillingChild(gameObjects[i].transform);
}
}
static void FillingChild(Transform transform)
{
for(int i = 0; i < transform.childCount; i++)
{
Joint joint = transform.GetChild(i).GetComponent<Joint>();
if(joint)
{
joint.connectedBody = transform.GetComponent<Rigidbody>();
FillingChild(joint.transform);
}
}
}
}