feat: 애니메이션 구간별 재생 속도 조절 에디터 툴 추가
- AnimationSectionSpeedEditor: 에디터 윈도우로 .anim 클립의 특정 프레임 구간 키프레임 간격 조절 - In-Memory API 방식(AnimationUtility + SerializedObject)로 FBX 타임라인 확장 문제 회피 - ImportAsset 미사용으로 Model Importer 재처리 차단 - 본/IK/prop/eyeLight 모든 커브 동시 수정, Humanoid muscle curve만 제외 - AnimationEvent 시간도 구간에 맞게 리맵핑 - 접선 스케일링으로 속도 변경 시 곡선 형태 유지 - ReverseAnimation: 애니메이션 반전 에디터 스크립트 추가
This commit is contained in:
83
Assets/_Game/Scripts/Editor/ReverseAnimation.cs
Normal file
83
Assets/_Game/Scripts/Editor/ReverseAnimation.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using UnityEngine;
|
||||
|
||||
using UnityEditor;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// 선택한 AnimationClip의 키프레임 순서를 반전합니다.
|
||||
/// FBX 임포트 클립에는 적용 불가 — 우선 Extract 후 사용하세요.
|
||||
/// </summary>
|
||||
public static class ReverseAnimation
|
||||
{
|
||||
public static AnimationClip GetSelectedClip()
|
||||
{
|
||||
var clips = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets);
|
||||
if (clips.Length > 0)
|
||||
return clips[0] as AnimationClip;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/ReverseAnimation")]
|
||||
public static void Reverse()
|
||||
{
|
||||
var clip = GetSelectedClip();
|
||||
if (clip == null)
|
||||
return;
|
||||
|
||||
float clipLength = clip.length;
|
||||
|
||||
List<AnimationCurve> curves = new List<AnimationCurve>();
|
||||
EditorCurveBinding[] editorCurveBindings = AnimationUtility.GetCurveBindings(clip);
|
||||
|
||||
foreach (EditorCurveBinding i in editorCurveBindings)
|
||||
{
|
||||
var curve = AnimationUtility.GetEditorCurve(clip, i);
|
||||
curves.Add(curve);
|
||||
}
|
||||
|
||||
clip.ClearCurves();
|
||||
|
||||
for (int i = 0; i < curves.Count; i++)
|
||||
{
|
||||
var curve = curves[i];
|
||||
var binding = editorCurveBindings[i];
|
||||
var keys = curve.keys;
|
||||
int keyCount = keys.Length;
|
||||
|
||||
var postWrapmode = curve.postWrapMode;
|
||||
curve.postWrapMode = curve.preWrapMode;
|
||||
curve.preWrapMode = postWrapmode;
|
||||
|
||||
for (int j = 0; j < keyCount; j++)
|
||||
{
|
||||
Keyframe K = keys[j];
|
||||
K.time = clipLength - K.time;
|
||||
|
||||
var tmp = -K.inTangent;
|
||||
K.inTangent = -K.outTangent;
|
||||
K.outTangent = tmp;
|
||||
|
||||
keys[j] = K;
|
||||
}
|
||||
|
||||
curve.keys = keys;
|
||||
clip.SetCurve(binding.path, binding.type, binding.propertyName, curve);
|
||||
}
|
||||
|
||||
// AnimationEvent 시간도 반전
|
||||
var events = AnimationUtility.GetAnimationEvents(clip);
|
||||
if (events.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < events.Length; i++)
|
||||
{
|
||||
events[i].time = clipLength - events[i].time;
|
||||
}
|
||||
AnimationUtility.SetAnimationEvents(clip, events);
|
||||
}
|
||||
|
||||
Debug.Log("[ReverseAnimation] Animation reversed: " + clip.name);
|
||||
EditorUtility.SetDirty(clip);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user