- Home /
Can I exclude a bone chain from animation so it can ragdoll?
I would like my character's hair to be dynamic. I have it rag-dolled, and it works how I want it to when there is no animation. I had hoped that simply not having channels or keys for the hair bones would do what I want, but it seems the entire rig gets tagged with "animation mode" regardless of whether or not there is animation information for each bone. (Understandable. It probably works better this way in most cases.)
After trying to figure it out myself I came to the conclusion that it will probably involve AddMixingTransform in some way, but I haven't had any luck with that so far.
How do I exclude a bone chain from animation so that I can make dynamic tails, hair, broken shackles, tassels, and wizard hats?
Answer by whydoidoit · Jun 18, 2012 at 08:49 AM
You are going to need to add mixing transforms for the animation without using the recursive parameter:
Recursively descend through the transforms in your skeleton yourself, doing an AddMixingTransform to each bone.
Store what you have added in a collection to reverse the operation later
Flag the transforms that are the root of your non-animated parts with a special script
Don't recurse or add the transform when you find the script on a transform
Here's my code for it - this might not won't work for you verbatim:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
public class $$anonymous$$ixCollection : IDisposable
{
private List<Transform> includedTransforms = new List<Transform>();
private AnimationState animationState;
public string RootTransformName;
public string[] SkipCategory;
public GameObject Character;
public string AnimationName;
public void Dispose()
{
foreach(var transform in includedTransforms)
{
animationState.Remove$$anonymous$$ixingTransform(transform);
}
//animationState.Get<$$anonymous$$ixing>().transforms.Clear();
}
public static $$anonymous$$ixCollection $$anonymous$$ix(GameObject character, string rootTransform, string animationName = "", string skipCategory = "")
{
var m = new $$anonymous$$ixCollection {
Character = character,
AnimationName = animationName,
RootTransformName = rootTransform,
SkipCategory = (skipCategory ?? "").Split(',')
};
return m;
}
public $$anonymous$$ixCollection Apply(string animationName = "")
{
AnimationName = string.IsNullOrEmpty(animationName) ? AnimationName : animationName;
animationState = Character.animation[AnimationName];
RecurseAddTransforms(FindTransform(Character.transform, RootTransformName));
return this;
}
void RecurseAddTransforms(Transform start)
{
Skip$$anonymous$$ixing skip;
if(( skip = start.GetComponent<Skip$$anonymous$$ixing>()) != null && SkipCategory.Contains(skip.Category))
{
return;
}
includedTransforms.Add(start);
animationState.Add$$anonymous$$ixingTransform(start, false);
foreach(var child in start.OfType<Transform>())
{
RecurseAddTransforms(child);
}
}
public static Transform FindTransform( Transform start, string name)
{
if(string.IsNullOrEmpty(name))
return start;
Transform ret;
if (start.name == name)
{
return start;
}
if (null != (ret = start.Find(name)))
{
return ret;
}
foreach (var child in start.OfType<Transform>())
{
if (null != (ret = FindTransform(child, name)))
{
return ret;
}
}
return null;
}
}
Oh you'd need this too:
Skip$$anonymous$$ixing.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
[AddComponent$$anonymous$$enu("Animation/Skip $$anonymous$$ixing")]
public class Skip$$anonymous$$ixing : $$anonymous$$onoBehaviour
{
public string Category;
}