将两个Avatar做lerp操作
public class BlendSkeleton : MonoBehaviour
{
public Animator animator;
private Avatar sourceAvatar;
public Avatar targetAvatar;
private Vector3 posForReset;
private Quaternion rotForReset;
public float Alpha
{
get => alpha;
set
{
alpha = value;
ResetAvatar();
}
}
private float alpha = 0f;
private void Awake()
{
if (animator == null)
{
bool found = TryGetComponent(out animator);
if (!found)
{
Debug.LogError("No animator found!");
}
}
sourceAvatar = animator.avatar;
}
void ResetAvatar()
{
float time = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
posForReset = transform.localPosition;
rotForReset = transform.localRotation;
Avatar avatar = LerpAvatars(gameObject, sourceAvatar, targetAvatar, alpha);
animator.avatar = avatar;
animator.Play("Idle", -1, time);
transform.localPosition = posForReset;
transform.localRotation = rotForReset;
}
public static Avatar LerpAvatars(GameObject root, Avatar a, Avatar b, float t)
{
HumanDescription aH = a.humanDescription;
HumanDescription bH = b.humanDescription;
var humanDescription = aH;
humanDescription.armStretch = Mathf.Lerp(aH.armStretch, bH.armStretch, t);
humanDescription.feetSpacing = Mathf.Lerp(aH.feetSpacing, bH.feetSpacing, t);
humanDescription.hasTranslationDoF = t > 0.5f ? bH.hasTranslationDoF : aH.hasTranslationDoF;
humanDescription.legStretch = Mathf.Lerp(aH.legStretch, bH.legStretch, t);
humanDescription.lowerArmTwist = Mathf.Lerp(aH.lowerArmTwist, bH.lowerArmTwist, t);
humanDescription.upperArmTwist = Mathf.Lerp(aH.upperArmTwist, bH.upperArmTwist, t);
humanDescription.lowerLegTwist = Mathf.Lerp(aH.lowerLegTwist, bH.lowerLegTwist, t);
humanDescription.upperLegTwist = Mathf.Lerp(aH.upperLegTwist, bH.upperLegTwist, t);
var aHSkeleton = aH.skeleton;
var aHHuman = aH.human;
var bHSkeleton = bH.skeleton;
var bHHuman = bH.human;
var skeletonBones = new SkeletonBone[aHSkeleton.Length];
humanDescription.skeleton = skeletonBones;
var humanBones = new HumanBone[aHHuman.Length];
humanDescription.human = humanBones;
for (int i = 0; i < humanDescription.skeleton.Length; i++)
{
float alpha = (aHSkeleton[i].name == bHSkeleton[i].name) ? t : 0f;
var skelement = new SkeletonBone
{
rotation = Quaternion.Slerp(aHSkeleton[i].rotation, bHSkeleton[i].rotation, alpha),
position = Vector3.Lerp(aHSkeleton[i].position, bHSkeleton[i].position, alpha),
scale = Vector3.Lerp(aHSkeleton[i].scale, bHSkeleton[i].scale, alpha),
name = aHSkeleton[i].name
};
skeletonBones[i] = skelement;
}
for (int i = 0; i < humanDescription.human.Length; i++)
{
if (aHHuman[i].boneName != bHHuman[i].boneName)
{
throw new InvalidOperationException("Skeleton arrays do not match, were these produced from the same original skeleton?");
}
var bone = new HumanBone
{
boneName = aHHuman[i].boneName,
humanName = aHHuman[i].humanName,
limit = new HumanLimit
{
max = Vector3.Lerp(aHHuman[i].limit.max, bHHuman[i].limit.max, t),
axisLength = Mathf.Lerp(aHHuman[i].limit.axisLength, bHHuman[i].limit.axisLength, t),
center = Vector3.Lerp(aHHuman[i].limit.center, bHHuman[i].limit.center, t),
min = Vector3.Lerp(aHHuman[i].limit.min, bHHuman[i].limit.min, t),
useDefaultValues = t > 0.5f ? aHHuman[i].limit.useDefaultValues : bHHuman[i].limit.useDefaultValues
}
};
humanBones[i] = bone;
}
humanDescription.skeleton = skeletonBones;
humanDescription.human = humanBones;
return AvatarBuilder.BuildHumanAvatar(root, humanDescription);
}
}