Created
September 17, 2018 10:58
-
-
Save shichiE/c8b7409ed519a62fe9b718c3a08af28b to your computer and use it in GitHub Desktop.
AnimatinClipのカーブのスパイクを均すエディタ拡張
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 自由に使ってどうぞ | |
// [Edit]フォルダに入れてメニューの[Animation Clip Smoother]-[Open]を選択するとウィンドウが表示される。 | |
// 編集するAnimationClipを選択後、編集するカーブを選択して[実行]ボタンを押す。 | |
using UnityEditor; | |
using UnityEngine; | |
public class AnimationClipSmoother : EditorWindow | |
{ | |
/// <summary> | |
/// 編集するAnimationClip | |
/// </summary> | |
private AnimationClip _selectAnimationClip = null; | |
/// <summary> | |
/// チェクする範囲 | |
/// </summary> | |
private int _range = 5; | |
/// <summary> | |
/// スパイク判定するしきい値 | |
/// </summary> | |
private float _threshold = 0.8f; | |
/// <summary> | |
/// 均したときの坂の勾配 | |
/// </summary> | |
private float _slopeLevel = 0f; | |
/// <summary> | |
/// 符号反転したときだけ均すかどうか | |
/// </summary> | |
private bool _isSignInversion = false; | |
/// <summary> | |
/// curve番号 | |
/// </summary> | |
private int _curveNumber; | |
/// <summary> | |
/// AnimationCipのプロパティ配列 | |
/// </summary> | |
private string[] _propertyNameArray = {""}; | |
[MenuItem("Animation Clip Smoother/Open")] | |
static void Open() | |
{ | |
GetWindow<AnimationClipSmoother>(); | |
} | |
void OnGUI() | |
{ | |
EditorGUI.BeginChangeCheck(); | |
_selectAnimationClip = EditorGUILayout.ObjectField( | |
"編集するアニメーションクリップ", | |
_selectAnimationClip, | |
typeof(AnimationClip), false) as AnimationClip; | |
// アニメーションクリップを選んだらそのプロパティをリスト要素にする | |
if (EditorGUI.EndChangeCheck()) | |
{ | |
int count = 0; | |
foreach (var binding in AnimationUtility.GetCurveBindings(_selectAnimationClip)) | |
{ | |
count++; | |
} | |
_propertyNameArray = new string[count]; | |
count = 0; | |
foreach (var binding in AnimationUtility.GetCurveBindings(_selectAnimationClip)) | |
{ | |
_propertyNameArray[count] = binding.propertyName; | |
count++; | |
} | |
} | |
_range = EditorGUILayout.IntSlider("1度にチェックする範囲", _range, 2, 50); | |
_threshold = EditorGUILayout.Slider("しきい値", _threshold, 0.001f, 10); | |
_slopeLevel = EditorGUILayout.Slider("坂の勾配", _slopeLevel, 0f, 0.1f); | |
_isSignInversion = EditorGUILayout.Toggle("符号が反転する場合のみ", _isSignInversion); | |
_curveNumber = EditorGUILayout.Popup("編集するカーブ", _curveNumber, _propertyNameArray); | |
bool clickExecuteButton = GUILayout.Button("実行"); | |
if (clickExecuteButton && _selectAnimationClip != null) | |
{ | |
string curveName = _propertyNameArray[_curveNumber]; | |
ClickExecuteButton(curveName); | |
} | |
} | |
/// <summary> | |
/// 実行ボタンを押したとき | |
/// </summary> | |
/// <param name="curveName">カーブ名</param> | |
private void ClickExecuteButton(string curveName) | |
{ | |
AnimationClip animationClip = _selectAnimationClip; | |
Debug.Log(animationClip.name); | |
foreach (var binding in AnimationUtility.GetCurveBindings(animationClip)) | |
{ | |
var curve = AnimationUtility.GetEditorCurve(animationClip, binding); | |
if (binding.propertyName.StartsWith(curveName)) | |
{ | |
Debug.Log(binding.propertyName + " KeyLength=" + curve.keys.Length); | |
curve = SmoothCurve(curve); | |
AnimationUtility.SetEditorCurve(animationClip, binding, curve); | |
} | |
} | |
} | |
/// <summary> | |
/// カーブをスパイクを均す | |
/// </summary> | |
/// <param name="curve">カーブ</param> | |
/// <returns>均したAnimationCurve</returns> | |
private AnimationCurve SmoothCurve(AnimationCurve curve) | |
{ | |
for (int i = 0; i < curve.keys.Length; i++) | |
{ | |
var max = float.MinValue; | |
var min = float.MaxValue; | |
var maxIndex = 0; | |
var minIndex = 0; | |
for (int count = 0; count < _range && i + count < curve.keys.Length; count++) | |
{ | |
if (min > curve.keys[i + count].value) | |
{ | |
min = curve.keys[i + count].value; | |
minIndex = i + count; | |
} | |
if (max < curve.keys[i + count].value) | |
{ | |
max = curve.keys[i + count].value; | |
maxIndex = i + count; | |
} | |
// しきい値を超えた場合キーフレームを移動させる | |
if (max - min > _threshold && | |
(!_isSignInversion || (max >= 0f && min <= 0f))) | |
{ | |
var index = 0; | |
if (curve.keys[i + count].value > min) | |
{ | |
Keyframe key = curve.keys[minIndex]; | |
// 坂の勾配をつける | |
for (index = minIndex + 1; | |
index < curve.keys.Length && | |
key.value < curve.keys[index].value; | |
index++) | |
{ | |
key.value += _slopeLevel; | |
Debug.Log("MoveKey index=" + index + " value=" + key.value); | |
curve.MoveKey(index, key); | |
curve.SmoothTangents(index, 1); | |
} | |
} | |
else | |
{ | |
Keyframe key = curve.keys[maxIndex]; | |
// 坂の勾配をつける | |
for (index = maxIndex + 1; | |
index < curve.keys.Length && | |
key.value > curve.keys[index].value; | |
index++) | |
{ | |
key.value -= _slopeLevel; | |
Debug.Log("MoveKey index=" + index + " value=" + key.value); | |
curve.MoveKey(index, key); | |
curve.SmoothTangents(index, 1); | |
} | |
} | |
} | |
} | |
} | |
return curve; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment