先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
318 lines
12 KiB
C#
318 lines
12 KiB
C#
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
|
|
[CustomEditor(typeof(CampTool))]
|
|
public class CampToolEditor : Editor
|
|
{
|
|
CampTool Temp;
|
|
public override void OnInspectorGUI()
|
|
{
|
|
//DrawDefaultInspector();
|
|
Temp = (CampTool)target;
|
|
// 显示文件夹路径
|
|
EditorGUILayout.LabelField("保存路径: " + Temp.folderPath);
|
|
if (GUILayout.Button("选择"))
|
|
{
|
|
// Temp.folderPath = EditorUtility.OpenFolderPanel("选择文件夹", Temp.folderPath, "");
|
|
var absPath = EditorUtility.OpenFolderPanel("选择文件夹", Temp.folderPath, "");
|
|
Temp.folderPath = absPath.Substring(absPath.IndexOf("Assets/"));
|
|
EditorUtility.SetDirty(Temp);
|
|
EditorSceneManager.SaveOpenScenes();
|
|
}
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("dynamic"));
|
|
EditorGUILayout.BeginVertical("box");
|
|
EditorGUILayout.Space();
|
|
|
|
GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
|
|
labelStyle.normal.textColor = Color.red; // Set the color you want
|
|
labelStyle.fontStyle = FontStyle.BoldAndItalic;
|
|
labelStyle.fontSize = 20;
|
|
labelStyle.wordWrap = true;
|
|
string labelText = "模版动画中每一个轨道,在动画最后一帧必须有关键帧,因为拿每一条轨道的最后一帧时间播放音效";
|
|
float labelHeight = labelStyle.CalcHeight(new GUIContent(labelText), EditorGUIUtility.currentViewWidth - 40);
|
|
|
|
EditorGUILayout.LabelField(labelText, labelStyle, GUILayout.Height(labelHeight));
|
|
|
|
EditorGUILayout.LabelField("生成初始动画", EditorStyles.boldLabel);
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("steps"));
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("targetLength"));
|
|
|
|
if (GUILayout.Button("Apply"))
|
|
{
|
|
Play();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.EndVertical();
|
|
//间隔
|
|
EditorGUILayout.Space(10);
|
|
EditorGUILayout.BeginVertical("box");
|
|
EditorGUILayout.LabelField("后续修改音效", EditorStyles.boldLabel);
|
|
EditorGUILayout.PropertyField(serializedObject.FindProperty("audioChangeDatas"));
|
|
if (GUILayout.Button("ChangeAudio"))
|
|
{
|
|
ChangeAudio();
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
public void Play()
|
|
{
|
|
for (int n = 0; n < Temp.steps.Length; n++)
|
|
{
|
|
StepRootData step = Temp.steps[n];
|
|
Transform root2 = step.StepRoot;
|
|
Transform root1 = root2.parent;
|
|
string path1 = root1.name;
|
|
string path2 = root2.name;
|
|
//创建新的AnimationClip
|
|
AnimationClip newAni = new AnimationClip();
|
|
if (string.IsNullOrEmpty(step.newAniName))
|
|
{
|
|
newAni.name = $"{path1}_{path2}";
|
|
}
|
|
else
|
|
{
|
|
newAni.name = step.newAniName;
|
|
}
|
|
List<int> timeList = new List<int>();
|
|
|
|
EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(step.ani);
|
|
|
|
int count = root2.childCount;
|
|
float bindingTime = 0f;
|
|
for (int j = 0; j < bindings.Length; j++)
|
|
{
|
|
var binding = bindings[j];
|
|
AnimationCurve curve = AnimationUtility.GetEditorCurve(step.ani, binding);
|
|
// 获取关键帧的数量
|
|
int keyCount = curve.keys.Length;
|
|
// 移动关键帧的位置
|
|
for (int k = keyCount - 1; k >= 0; k--)
|
|
{
|
|
Keyframe key = curve.keys[k];
|
|
key.time += 0.02f;
|
|
if (bindingTime < key.time)
|
|
{
|
|
bindingTime = key.time;
|
|
}
|
|
curve.MoveKey(k, key);
|
|
}
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
// string trackName = $"{path1}/{path2}/{i + 1}/AnimRoot";
|
|
string trackName = $"{path1}/{path2}/{i + 1:D2}/AnimRoot";
|
|
EditorCurveBinding trackBinding = new EditorCurveBinding
|
|
{
|
|
type = binding.type,
|
|
path = trackName,
|
|
propertyName = binding.propertyName
|
|
};
|
|
|
|
// 将轨道添加到Clip中
|
|
AnimationUtility.SetEditorCurve(newAni, trackBinding, curve);
|
|
if (j == 0 && step.audioClip != null)
|
|
{
|
|
int keyTime = Mathf.RoundToInt(bindingTime * 10000);
|
|
if (!timeList.Contains(keyTime))
|
|
{
|
|
timeList.Add(keyTime);
|
|
}
|
|
}
|
|
// 移动关键帧的位置
|
|
for (int k = keyCount - 1; k >= 0; k--)
|
|
{
|
|
Keyframe key = curve.keys[k];
|
|
key.time += step.timeAniOffset;
|
|
if (bindingTime < key.time)
|
|
{
|
|
bindingTime = key.time;
|
|
}
|
|
curve.MoveKey(k, key);
|
|
}
|
|
|
|
}
|
|
}
|
|
if (step.audioClip != null)
|
|
{
|
|
SetBindingAudio(timeList, newAni, step.audioClip);
|
|
}
|
|
|
|
if (Temp.targetLength > 0)
|
|
{
|
|
// Get the original length of the clip
|
|
float originalLength = newAni.length;
|
|
if (originalLength <= 0)
|
|
{
|
|
Debug.LogWarning($"Clip '{newAni.name}' has no length to scale.");
|
|
continue;
|
|
}
|
|
|
|
// Calculate the new speed to scale the animation
|
|
float scaleFactor = originalLength / Temp.targetLength;
|
|
|
|
// Scale the animation clip speed by adjusting its frame rates
|
|
ScaleClip(newAni, scaleFactor);
|
|
}
|
|
|
|
AssetDatabase.CreateAsset(newAni, $"{Temp.folderPath}/{newAni.name}.anim");
|
|
}
|
|
//保存 Temp
|
|
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
void SetBindingAudio(List<int> timeList, AnimationClip newAni, AudioClip audioClip)
|
|
{
|
|
List<EditorCurveBinding> bindingAudio = new List<EditorCurveBinding>();
|
|
List<AnimationCurve> curveAudio = new List<AnimationCurve>();
|
|
int audioIndex = 0;
|
|
Keyframe keyframe = new Keyframe(0, 0, Mathf.Infinity, Mathf.Infinity);
|
|
string AudioRoot = "Audio";
|
|
Transform AudioTran = Temp.dynamic.Find(AudioRoot);
|
|
if (AudioTran == null)
|
|
{
|
|
GameObject go = new GameObject(AudioRoot);
|
|
go.transform.SetParent(Temp.dynamic);
|
|
AudioTran = go.transform;
|
|
}
|
|
int maxTime = 0;
|
|
for (int j = 0; j < timeList.Count; j++)
|
|
{
|
|
audioIndex %= 3;
|
|
|
|
Transform tran2 = AudioTran.Find($"{newAni.name}_{audioIndex}");
|
|
AudioSource aud;
|
|
if (tran2)
|
|
{
|
|
aud = tran2.GetComponent<AudioSource>();
|
|
}
|
|
else
|
|
{
|
|
var go = new GameObject($"{newAni.name}_{audioIndex}", typeof(AudioSource));
|
|
go.transform.SetParent(AudioTran);
|
|
aud = go.GetComponent<AudioSource>();
|
|
go.SetActive(false);
|
|
}
|
|
aud.clip = audioClip;
|
|
if (bindingAudio.Count <= audioIndex)
|
|
{
|
|
bindingAudio.Add(new EditorCurveBinding
|
|
{
|
|
type = typeof(GameObject),
|
|
path = $"{AudioRoot}/{newAni.name}_{audioIndex}",
|
|
propertyName = "m_IsActive"
|
|
});
|
|
|
|
}
|
|
if (curveAudio.Count <= audioIndex)
|
|
{
|
|
curveAudio.Add(new AnimationCurve());
|
|
curveAudio[audioIndex].AddKey(keyframe);
|
|
}
|
|
if (maxTime < timeList[j])
|
|
{
|
|
maxTime = timeList[j];
|
|
}
|
|
float time = timeList[j] / 10000f;
|
|
Keyframe key2 = new Keyframe(time - 0.02f, 0, Mathf.Infinity, Mathf.Infinity);
|
|
Keyframe key3 = new Keyframe(time, 1, Mathf.Infinity, Mathf.Infinity);
|
|
curveAudio[audioIndex].AddKey(key2);
|
|
curveAudio[audioIndex].AddKey(key3);
|
|
audioIndex++;
|
|
}
|
|
for (int i = 0; i < bindingAudio.Count; i++)
|
|
{
|
|
if (newAni == null || bindingAudio[i] == null || curveAudio[i] == null)
|
|
continue;
|
|
float time = maxTime / 10000f;
|
|
Keyframe key = new Keyframe(time, 0);
|
|
curveAudio[i].AddKey(key);
|
|
int lastKey = curveAudio[i].length - 1;
|
|
curveAudio[i].MoveKey(lastKey, key);
|
|
AnimationUtility.SetEditorCurve(newAni, bindingAudio[i], curveAudio[i]);
|
|
}
|
|
}
|
|
|
|
public void ChangeAudio()
|
|
{
|
|
for (int n = 0; n < Temp.audioChangeDatas.Length; n++)
|
|
{
|
|
AudioChangeData data = Temp.audioChangeDatas[n];
|
|
AnimationClip newAni = data.ani;
|
|
EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(data.ani);
|
|
|
|
List<int> timeList = new List<int>();
|
|
|
|
for (int j = 0; j < bindings.Length; j++)
|
|
{
|
|
var binding = bindings[j];
|
|
if (binding.path.Contains($"Audio/{newAni.name}"))
|
|
{
|
|
continue;
|
|
}
|
|
AnimationCurve curve = AnimationUtility.GetEditorCurve(data.ani, binding);
|
|
// 获取关键帧的数量
|
|
int keyCount = curve.keys.Length;
|
|
|
|
Keyframe key = curve.keys[keyCount - 1];
|
|
int keyTime = Mathf.RoundToInt(key.time * 10000);
|
|
if (!timeList.Contains(keyTime))
|
|
{
|
|
timeList.Add(keyTime);
|
|
}
|
|
}
|
|
SetBindingAudio(timeList, newAni, data.audioClip);
|
|
EditorUtility.SetDirty(data.ani);
|
|
}
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
private void ScaleClip(AnimationClip clip, float scaleFactor)
|
|
{
|
|
// Debug.Log($"<color=red>{scaleFactor} for {clip}</color>");
|
|
// Scale all curves in the clip
|
|
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
|
|
{
|
|
var curve = AnimationUtility.GetEditorCurve(clip, binding);
|
|
var curveKeyFrames = curve.keys;
|
|
// Adjust keyframe times
|
|
for (int i = 0; i < curveKeyFrames.Length; i++)
|
|
{
|
|
// Debug.Log($" before: {curveKeyFrames[i].time}");
|
|
// var t = curveKeyFrames[i].time / scaleFactor;
|
|
// curve.keys[i].time = t;
|
|
curveKeyFrames[i].time /= scaleFactor;
|
|
// Debug.Log($" after: {curveKeyFrames[i].time}");
|
|
// Debug.Log($" after t: {t}");
|
|
}
|
|
|
|
curve.keys = curveKeyFrames;
|
|
AnimationUtility.SetEditorCurve(clip, binding, curve);
|
|
}
|
|
|
|
foreach (var binding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
|
|
{
|
|
var curve = AnimationUtility.GetEditorCurve(clip, binding);
|
|
for (int i = 0; i < curve.keys.Length; i++)
|
|
{
|
|
curve.keys[i].time /= scaleFactor;
|
|
}
|
|
AnimationUtility.SetEditorCurve(clip, binding, curve);
|
|
}
|
|
|
|
// Scale events
|
|
foreach (var animEvent in AnimationUtility.GetAnimationEvents(clip))
|
|
{
|
|
animEvent.time /= scaleFactor;
|
|
}
|
|
|
|
// Apply changes back to the clip
|
|
AnimationUtility.SetAnimationEvents(clip, AnimationUtility.GetAnimationEvents(clip));
|
|
Debug.Log($"Scaled clip '{clip.name}' to {clip.length / scaleFactor} seconds.");
|
|
}
|
|
}
|