/// <summary> /// Animatorと記録したデータで書き込む /// </summary> /// <param name="root"></param> /// <param name="facial"></param> void ExportFacialAnimationClip(Animator root, CharacterFacialData facial) { var animclip = new AnimationClip(); var mesh = _smeshs; for (int faceTargetMeshIndex = 0; faceTargetMeshIndex < mesh.Length; faceTargetMeshIndex++) { var pathsb = new StringBuilder().Append(mesh[faceTargetMeshIndex].transform.name); var trans = mesh[faceTargetMeshIndex].transform; while (trans.parent != null && trans.parent != root.transform) { trans = trans.parent; pathsb.Insert(0, "/").Insert(0, trans.name); } //pathにはBlendshapeのベース名が入る //U_CHAR_1:SkinnedMeshRendererみたいなもの var path = pathsb.ToString(); //個別メッシュの個別Blendshapeごとに、AnimationCurveを生成している for (var blendShapeIndex = 0; blendShapeIndex < mesh[faceTargetMeshIndex].sharedMesh.blendShapeCount; blendShapeIndex++) { var curveBinding = new EditorCurveBinding(); curveBinding.type = typeof(SkinnedMeshRenderer); curveBinding.path = path; curveBinding.propertyName = "blendShape." + mesh[faceTargetMeshIndex].sharedMesh.GetBlendShapeName(blendShapeIndex); AnimationCurve curve = new AnimationCurve(); float pastBlendshapeWeight = -1; for (int k = 0; k < _facialData.Facials.Count; k++) { if (!(Mathf.Abs(pastBlendshapeWeight - _facialData.Facials[k].Smeshes[faceTargetMeshIndex].blendShapes[blendShapeIndex]) > 0.1f)) { continue; } curve.AddKey(new Keyframe(facial.Facials[k].Time, _facialData.Facials[k].Smeshes[faceTargetMeshIndex].blendShapes[blendShapeIndex], float.PositiveInfinity, 0f)); pastBlendshapeWeight = _facialData.Facials[k].Smeshes[faceTargetMeshIndex].blendShapes[blendShapeIndex]; } AnimationUtility.SetEditorCurve(animclip, curveBinding, curve); } } MotionDataRecorder.SafeCreateDirectory("Assets/Resources"); var outputPath = "Assets/Resources/FaceRecordMotion_" + _animRecorder.CharacterAnimator.name + "_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + "_Clip.anim"; Debug.Log("outputPath:" + outputPath); AssetDatabase.CreateAsset(animclip, AssetDatabase.GenerateUniqueAssetPath(outputPath)); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
/// <summary> /// 記録開始 /// </summary> private void RecordStart() { if (_recordFaceBlendshapes == false) { return; } if (_recording) { return; } if (_smeshs.Length == 0) { Debug.LogError("顔のメッシュ指定がされていないので顔のアニメーションは記録しません"); return; } Debug.Log("FaceAnimationRecorder record start"); _recording = true; _recordedTime = 0f; _startTime = Time.time; _frameCount = 0; _facialData = ScriptableObject.CreateInstance <CharacterFacialData>(); }
/// <summary> /// Animatorと記録したデータで書き込む /// </summary> /// <param name="root"></param> /// <param name="facial"></param> void ExportFacialAnimationClip(Animator root, CharacterFacialData facial) { var animclip = new AnimationClip(); var mesh = _smeshs; for (int i = 0; i < mesh.Length; i++) { var pathsb = new StringBuilder().Append(mesh[i].transform.name); var trans = mesh[i].transform; while (trans.parent != null && trans.parent != root.transform) { trans = trans.parent; pathsb.Insert(0, "/").Insert(0, trans.name); } var path = pathsb.ToString(); for (var j = 0; j < mesh[i].sharedMesh.blendShapeCount; j++) { var curveBinding = new EditorCurveBinding(); curveBinding.type = typeof(SkinnedMeshRenderer); curveBinding.path = path; curveBinding.propertyName = "blendShape." + mesh[i].sharedMesh.GetBlendShapeName(j); AnimationCurve curve = new AnimationCurve(); float pastBlendshapeWeight = -1; for (int k = 0; k < _facialData.Facials.Count; k++) { if (!(Mathf.Abs(pastBlendshapeWeight - _facialData.Facials[k].Smeshes[i].blendShapes[j]) > 0.1f)) { continue; } curve.AddKey(facial.Facials[k].Time, _facialData.Facials[k].Smeshes[i].blendShapes[j]); pastBlendshapeWeight = _facialData.Facials[k].Smeshes[i].blendShapes[j]; } AnimationUtility.SetEditorCurve(animclip, curveBinding, curve); } } MotionDataRecorder.SafeCreateDirectory("Assets/Resources"); var outputPath = "Assets/Resources/FaceRecordMotion_" + _animRecorder.CharacterAnimator.name + "_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + "_Clip.anim"; Debug.Log("outputPath:" + outputPath); AssetDatabase.CreateAsset(animclip, AssetDatabase.GenerateUniqueAssetPath(outputPath)); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }