Hello,
I have a humanoid character. The character is animated by an animator or procedurally (for example by rotating its node in the editor). Let’s call him A.
I have a second character, called B. B has a different skeleton, with other axes, etc. I need to copy, by code, at runtime the transforms of skeleton A to replicate its animation on B.
I tested to compute and cache the rotation offset of each bone between A and B at startup and multiply it by the rotation of the animated character and write it to B, with no success. If you turn the head along the Yaw axis, it will turn around the Pitch axis on the second skeleton.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CopySkeleton : MonoBehaviour
{
public Animator animatorSrc;
public Animator animatorDst;
private Dictionary<HumanBodyBones, Quaternion> rigDefRotationDst = null;
void Start()
{
rigDefRotationDst = new Dictionary<HumanBodyBones, Quaternion>();
// Difference C between Quaternions A and B:
// C = A * Quaternion.Inverse(B);
for (int i = 0; i < ((int)(HumanBodyBones.LastBone) - 1); i++)
{
HumanBodyBones BoneType = (HumanBodyBones)i;
Transform trSrc = animatorSrc.GetBoneTransform(BoneType);
Transform trDst = animatorDst.GetBoneTransform(BoneType);
Quaternion Q = trDst.rotation * Quaternion.Inverse(trSrc.rotation);
rigDefRotationDst.Add(BoneType, Q);
}
}
void Update()
{
int BoneCount = (int)(HumanBodyBones.LastBone) - 1;
for (int i = 0; i < BoneCount; i++)
{
HumanBodyBones CurrentBone = (HumanBodyBones)i;
Transform Src = animatorSrc.GetBoneTransform(CurrentBone);
Transform Dst = animatorDst.GetBoneTransform(CurrentBone);
if (Src == null || Dst == null)
continue;
CopyJoint(Src, Dst, rigDefRotationDst[CurrentBone]);
}
}
private void CopyJoint(Transform _Src, Transform _Dst, Quaternion _PoseOfs)
{
// Quat D = C * D;
_Dst.rotation = _PoseOfs*_Src.rotation;
}
}
Any idea how to manage it?
Thanks in advance!