private static void GenerateClip(List <SkinBone> bones, AnimationClip clip, string file) { EditorCurveBinding[] curveDatas = AnimationUtility.GetCurveBindings(clip); float frequency = 1.0f / 30.0f; int keyframeLen = (int)Mathf.Ceil(clip.length / frequency) + 1; List <float> times = new List <float>(); for (int i = 0; i < keyframeLen; ++i) { times.Add(i * frequency >= clip.length ? clip.length : i * frequency); } SkinAnimationClip newClip = ScriptableObject.CreateInstance <SkinAnimationClip>(); newClip.frequency = frequency; newClip.times = times.ToArray(); newClip.datas = new float[bones.Count * keyframeLen * SkinAnimationClip.STRIDE]; newClip.length = clip.length; newClip.animName = clip.name; newClip.nodeCount = bones.Count; Dictionary <string, int> boneIndexMap = new Dictionary <string, int>(); for (int i = 0; i < bones.Count; ++i) { SkinBone bone = bones[i]; Vector3 pos = bone.transform.localPosition; Quaternion rot = bone.transform.localRotation; int frameIndex = i * keyframeLen * SkinAnimationClip.STRIDE; for (int j = 0; j < keyframeLen; ++j) { int curveIndex = j * SkinAnimationClip.STRIDE; newClip.datas[frameIndex + curveIndex + 0] = pos.x; newClip.datas[frameIndex + curveIndex + 1] = pos.y; newClip.datas[frameIndex + curveIndex + 2] = pos.z; newClip.datas[frameIndex + curveIndex + 3] = rot.x; newClip.datas[frameIndex + curveIndex + 4] = rot.y; newClip.datas[frameIndex + curveIndex + 5] = rot.z; newClip.datas[frameIndex + curveIndex + 6] = rot.w; } boneIndexMap[bone.transform.name] = i; } float[] values = new float[keyframeLen]; for (int i = 0; i < curveDatas.Length; ++i) { EditorCurveBinding binding = curveDatas[i]; string name = binding.path.Substring(binding.path.LastIndexOf('/') + 1); AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding); int offset = -1; switch (binding.propertyName) { case "m_LocalPosition.x": offset = 0; break; case "m_LocalPosition.y": offset = 1; break; case "m_LocalPosition.z": offset = 2; break; case "m_LocalRotation.x": offset = 3; break; case "m_LocalRotation.y": offset = 4; break; case "m_LocalRotation.z": offset = 5; break; case "m_LocalRotation.w": offset = 6; break; } if (offset == -1) { continue; } if (!boneIndexMap.ContainsKey(name)) { continue; } for (int j = 0; j < keyframeLen; ++j) { values[j] = curve.Evaluate(times[j]); } int frameIndex = boneIndexMap[name] * keyframeLen * SkinAnimationClip.STRIDE; for (int j = 0; j < keyframeLen; ++j) { int curveIndex = j * SkinAnimationClip.STRIDE; newClip.datas[frameIndex + curveIndex + offset] = values[j]; } } string basePath = Path.GetDirectoryName(file) + "/" + Path.GetFileNameWithoutExtension(file); string clipPath = basePath + clip.name + ".anim.asset"; AssetDatabase.CreateAsset(newClip, clipPath); AnimationClip emptyClip = new AnimationClip(); AnimationCurve emptyCurve = new AnimationCurve(); emptyCurve.AddKey(new Keyframe(0.0f, 0.0f)); emptyCurve.AddKey(new Keyframe(clip.length, clip.length)); emptyClip.SetCurve("", typeof(SkinFloat), "value", emptyCurve); AssetDatabase.CreateAsset(emptyClip, basePath + clip.name + ".anim"); }
private float[] CalculateCurrentPose() { SkinAnimationClip currClip = null; float currBias = 1.0f; float currTime = 0.0f; if (m_Animator.GetCurrentAnimatorClipInfoCount(0) > 0) { var clipInfo = m_Animator.GetCurrentAnimatorClipInfo(0)[0]; var stateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); currTime = stateInfo.normalizedTime * clipInfo.clip.length; currClip = m_ClipsMap[clipInfo.clip.name]; currBias = clipInfo.weight; } SkinAnimationClip nextClip = null; float nextBias = 1.0f; float nextTime = 0.0f; if (m_Animator.GetNextAnimatorClipInfoCount(0) > 0) { var clipInfo = m_Animator.GetNextAnimatorClipInfo(0)[0]; var stateInfo = m_Animator.GetNextAnimatorStateInfo(0); nextTime = stateInfo.normalizedTime * clipInfo.clip.length; nextClip = m_ClipsMap[clipInfo.clip.name]; nextBias = clipInfo.weight; } float[] finalPose = null; if (currClip != null && currBias > 0.0f) { currClip.Evaluate(Mathf.Repeat(currTime, currClip.length), TEMP_POSE_DATA0, false); finalPose = TEMP_POSE_DATA0; } if (nextClip != null && nextBias > 0.0f) { nextClip.Evaluate(Mathf.Repeat(nextTime, nextClip.length), TEMP_POSE_DATA1, false); finalPose = TEMP_POSE_DATA1; } if ((currClip != null && currBias > 0.0f) && (nextClip != null && nextBias > 0.0f)) { float total = currBias + nextBias; currBias /= total; nextBias /= total; finalPose = TEMP_POSE_DATA0; for (int i = 1; i < avatar.bonesName.Length; ++i) { int idx = i * SkinAnimationClip.STRIDE; for (int j = 0; j < SkinAnimationClip.STRIDE; ++j) { float a = TEMP_POSE_DATA0[idx + j]; float b = TEMP_POSE_DATA1[idx + j]; finalPose[idx + j] = a * currBias + b * nextBias; } } } return(finalPose); }