Skip to content

Commit

Permalink
Add blendShape recording function to UnityAnimationRecorder
Browse files Browse the repository at this point in the history
  • Loading branch information
newyellow committed Mar 1, 2018
1 parent 3f5f31f commit c800de0
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class UnityAnimationRecorderEditor : Editor {
SerializedProperty showLogGUI;
SerializedProperty recordLimitedFrames;
SerializedProperty recordFrames;
SerializedProperty recordBlendShape;

SerializedProperty changeTimeScale;
SerializedProperty timeScaleOnStart;
Expand All @@ -33,6 +34,7 @@ void OnEnable () {
showLogGUI = serializedObject.FindProperty ("showLogGUI");
recordLimitedFrames = serializedObject.FindProperty ("recordLimitedFrames");
recordFrames = serializedObject.FindProperty ("recordFrames");
recordBlendShape = serializedObject.FindProperty ("recordBlendShape");

changeTimeScale = serializedObject.FindProperty ("changeTimeScale");
timeScaleOnStart = serializedObject.FindProperty ("timeScaleOnStart");
Expand Down Expand Up @@ -70,6 +72,7 @@ public override void OnInspectorGUI () {

// Other Settings
EditorGUILayout.LabelField( "== Other Settings ==" );
recordBlendShape.boolValue = EditorGUILayout.Toggle ("Record BlendShapes", recordBlendShape.boolValue);
bool timeScaleOption = EditorGUILayout.Toggle ( "Change Time Scale", changeTimeScale.boolValue);
changeTimeScale.boolValue = timeScaleOption;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

public class UnityAnimationRecorder : MonoBehaviour {

Expand All @@ -27,8 +28,13 @@ public class UnityAnimationRecorder : MonoBehaviour {
public float timeScaleOnStart = 0.0f;
public float timeScaleOnRecord = 1.0f;

public bool recordBlendShape = false;


Transform[] recordObjs;
SkinnedMeshRenderer[] blendShapeObjs;
UnityObjectAnimation[] objRecorders;
List<UnityBlendShapeAnimation> blendShapeRecorders;

bool isStart = false;
float nowTime = 0.0f;
Expand All @@ -42,13 +48,26 @@ void Start () {
void SetupRecorders () {
recordObjs = gameObject.GetComponentsInChildren<Transform> ();
objRecorders = new UnityObjectAnimation[recordObjs.Length];
blendShapeRecorders = new List<UnityBlendShapeAnimation> ();

frameIndex = 0;
nowTime = 0.0f;

for (int i = 0; i < recordObjs.Length; i++) {
string path = AnimationRecorderHelper.GetTransformPathName (transform, recordObjs [i]);
objRecorders [i] = new UnityObjectAnimation ( path, recordObjs [i]);

// check if theres blendShape
if (recordBlendShape) {
if (recordObjs [i].GetComponent<SkinnedMeshRenderer> ()) {
SkinnedMeshRenderer tempSkinMeshRenderer = recordObjs [i].GetComponent<SkinnedMeshRenderer> ();

// there is blendShape exist
if (tempSkinMeshRenderer.sharedMesh.blendShapeCount > 0) {
blendShapeRecorders.Add (new UnityBlendShapeAnimation (path, tempSkinMeshRenderer));
}
}
}
}

if (changeTimeScale)
Expand All @@ -72,6 +91,12 @@ void Update () {
for (int i = 0; i < objRecorders.Length; i++) {
objRecorders [i].AddFrame (nowTime);
}

if (recordBlendShape) {
for (int i = 0; i < blendShapeRecorders.Count; i++) {
blendShapeRecorders [i].AddFrame (nowTime);
}
}
}

}
Expand Down Expand Up @@ -145,6 +170,18 @@ void ExportAnimationClip () {
}
}

if (recordBlendShape) {
for (int i = 0; i < blendShapeRecorders.Count; i++) {

UnityCurveContainer[] curves = blendShapeRecorders [i].curves;

for (int x = 0; x < curves.Length; x++) {
clip.SetCurve (blendShapeRecorders [i].pathName, typeof(SkinnedMeshRenderer), curves [x].propertyName, curves [x].animCurve);
}

}
}

clip.EnsureQuaternionContinuity ();
AssetDatabase.CreateAsset ( clip, exportFilePath );

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using UnityEngine;
using System.Collections;

public class UnityBlendShapeAnimation {

public UnityCurveContainer[] curves;
public SkinnedMeshRenderer skinMeshObj;
string[] blendShapeNames;
int blendShapeCount = 0;
public string pathName = "";

public UnityBlendShapeAnimation( string hierarchyPath, SkinnedMeshRenderer observeSkinnedMeshRenderer ) {
pathName = hierarchyPath;
skinMeshObj = observeSkinnedMeshRenderer;

//int blendShapeCount = skinMeshObj.getbl
Mesh blendShapeMesh = skinMeshObj.sharedMesh;
blendShapeCount = blendShapeMesh.blendShapeCount;

blendShapeNames = new string[blendShapeCount];
curves = new UnityCurveContainer[blendShapeCount];

// create curve objs and add names
for (int i = 0; i < blendShapeCount; i++) {
blendShapeNames [i] = blendShapeMesh.GetBlendShapeName (i);
curves [i] = new UnityCurveContainer ("blendShape." + blendShapeNames [i]);
}
}

public void AddFrame ( float time ) {

for (int i = 0; i < blendShapeCount; i++)
curves [i].AddValue (time, skinMeshObj.GetBlendShapeWeight (i));

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 comments on commit c800de0

@physicsssss
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this repository free to use?
also if it is open source can i contribute to it too?

@newyellow
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@physicsssss yes, everything is open source. Please feel free to contribute!

@bstall-sudo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks a lot for the code!

I am new in Unity!

I have two questions:

  1. Will the saved Animationclips be marked as Legacy? I am asking that, because after recording and saving them at runtime, I have to load them at runtime. And that seems to be difficult:
    https://forum.unity.com/threads/cannot-load-animation-clip-from-asset-bundle-how-to-set-animation-clip-to-legacy-in-code.483253/

  2. Could you tell me how to set everything up, so that it works?
    I put 6 Scripts into my Scriptsfolder: AnimationRecorderHelper, UnityAnimationRecorder, UnityAnimationRecorderEditor, UnityBlendShapeAnimation, UnityCurveContainer, UnityObjectAnimation.
    I attached the Unity AnimationRecorder to the Gameobject, that I want to record. A humanoid character (the humanoid character is animated via input from the steamvr htc xrrig. I filled in the Save Path: Assets/StreamingAssets. I chose a filename.
    I press play. There is no Error, in the inspector tab "List of Record Obj" appear all bone children of the rig. Everything seems to be allright. I press "q" for start an "w" stop. But then there is no message in the Console about the progress (start recording or stop recording). And there is no saved file in the StreamingAssets folder and no error message.

Would be really great to hear from you, because this is the last unsolved problem of my project.

Thanks a lot!

@newyellow
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @bstall-sudo

  1. The animation's label (legacy, humanoid) is only used when you importing models. There's no difference when it is a .anim unity animation format. You can try exporting the animation with models and then import again, like is this thread:
    When I used "FBX Exporter", I got error message #17

  2. You can try with demo scene and see how it works. And the script is also readable so you may also figuring out the flow with it.

@bstall-sudo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, Thanks a lot. I will try that!

Please sign in to comment.