Skip to content

Instantly share code, notes, and snippets.

@undefined9071
Created October 8, 2023 06:52
Show Gist options
  • Save undefined9071/9b9caec1b5597769b0afda6ca03049ec to your computer and use it in GitHub Desktop.
Save undefined9071/9b9caec1b5597769b0afda6ca03049ec to your computer and use it in GitHub Desktop.
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class TimelineRecorder : MonoBehaviour {
[SerializeField] public PlayableDirector director;
[SerializeField] public GameObject rootBone;
[HideInInspector] public GameObjectRecorder m_Recorder;
// 0.05f : low compression, slow, high quality
// 0.1f : high compression, fast, low quality
[SerializeField] public float positionError = 0.05f;
[SerializeField] public float rotationError = 0.05f;
}
#if UNITY_EDITOR
[CustomEditor(typeof(TimelineRecorder))]
[CanEditMultipleObjects]
public class TimelineRecorderCustomEditor : Editor {
static TimelineRecorder Instance;
public override void OnInspectorGUI() {
base.OnInspectorGUI();
Instance = target as TimelineRecorder;
EditorGUILayout.HelpBox("SHOW THE GAME WINDOW IN THE FOREGROUND", MessageType.Warning, true);
EditorGUILayout.Space(10);
if (GUILayout.Button("\nRecording\n")) {
Instance.StartCoroutine(RecordingTimeline());
}
}
private IEnumerator RecordingTimeline() {
var timelineAsset = Instance.director.playableAsset as TimelineAsset;
var clipFrameCount = Mathf.RoundToInt((float) Instance.director.duration * (float) timelineAsset.editorSettings.frameRate);
int frame = 0;
Instance.director.time = 0;
yield return new WaitForSeconds(1);
Instance.director.Play();
Instance.director.playableGraph.GetRootPlayable(0).SetSpeed(0);
AnimationClip clip = new AnimationClip();
clip.name = Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(timelineAsset));
clip.frameRate = 60;
Instance.m_Recorder = new GameObjectRecorder(Instance.rootBone);
Instance.m_Recorder.BindComponentsOfType<Transform>(Instance.rootBone, true);
while (frame < clipFrameCount) {
Instance.director.time = frame / timelineAsset.editorSettings.frameRate;
Instance.director.playableGraph.GetRootPlayable(0).SetSpeed(0);
yield return new WaitForEndOfFrame();
Instance.m_Recorder.TakeSnapshot(0.01666666666666667f);
Debug.Log(frame + ": done");
frame++;
}
Debug.Log("finished");
var options = new CurveFilterOptions();
options.keyframeReduction = true;
options.scaleError = 0.05f;
options.positionError = Instance.positionError;
options.rotationError = Instance.rotationError;
Instance.m_Recorder.SaveToClip(clip, 60, options);
var assetPath = $"{System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(timelineAsset))}/{clip.name}.anim";
if (File.Exists(assetPath)) {
AssetDatabase.DeleteAsset(assetPath);
}
AssetDatabase.CreateAsset(clip, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
#endif
@undefined9071
Copy link
Author

  • Require Unity2020.3^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment