当我尝试对动画剪辑应用替代时。它给了我这个警告并停止了程序。
“无法在Transform组件上绑定通用曲线,仅支持位置,旋转和比例曲线。”
void CopyAnimationClip()
{
Animation_Copy = new AnimationClip();
for (int i = 0; i < keyframedata.Length; i++)
{
AnimationCurve newCurve = new AnimationCurve(keyframedata[i]);
Animation_Copy.SetCurve(RelativePath[i], typeof(Transform), propertyName[i], newCurve);
}
animOverride["BounceAnimation"] = Animation_Copy; //Where the warning comes from
}
此处的propertyName是“ LocalPosition.y”,“ LocalScale.y”,“ LocalScale.x”。而且RelativePath为空(我正在为根对象设置动画)。
令我感到奇怪的是 仅当我尝试将动画数据导出到文件然后将其重新导入时,才会发生这种情况。当我直接从动画剪辑中读取动画数据并将其放回原处时(我有另一段代码可以从动画剪辑中读取数据并将它们存储到上面的数组中)。我将数据以纯文本格式保存。这可能是问题吗? (我仍然对序列化和反序列化感到困惑,因此我没有使用它们)
对DerHugo的问题
是的,有一些区别。因为我从动画中读取的属性名称是“ m_LocalePosition.y”,并且在构造函数中使用它创建曲线时(同样,仅当我尝试从文件加载时),Unity给了我
“由于m_LocalPosition.y,无法分配曲线 不是有效的Transform属性。”
然后我检查了API的统一动画,似乎没有类似“ m_”的内容,因此在将其写入文件之前必须先执行此操作。在运行时直接从Unity动画剪辑中读取它时,不需要此步骤。
propertyName[i] = propertyName[i].Replace("m_", "");
然后我可以创建曲线,然后得到上面的问题。
这是我用来从动画剪辑中读取数据的代码
void LoadAnimationDataFromEditor()
{
//Get the curve binding in the animation.
UnityEditor.EditorCurveBinding[] curveBindings = UnityEditor.AnimationUtility.GetCurveBindings(InputAnimation);
//Get the binded curve in the curve binding.
AnimationCurve[] curves = new AnimationCurve[curveBindings.Length];
//Create and store the data needed to create a curve
keyframedata = new Keyframe[curves.Length][];
//The array to keep the original keyframe value.
keyframeValues = new float[curves.Length][];
RelativePath = new string[curves.Length];
propertyName = new string[curves.Length];
for (int i = 0; i < curves.Length; i++)
{
//Store curve data
RelativePath[i] = curveBindings[i].path;
propertyName[i] = curveBindings[i].propertyName;
curves[i] = UnityEditor.AnimationUtility.GetEditorCurve(InputAnimation, curveBindings[i]);
//Get key frame in each curve
Keyframe[] keyframes = curves[i].keys;
//Create an array of keyframes to store the game keyframe data
keyframedata[i] = new Keyframe[curves[i].keys.Length];
keyframeValues[i] = new float[curves[i].keys.Length];
for (int a = 0; a < keyframes.Length; a++)
{
//Copy the keyframe data to array for editing test
keyframedata[i][a] = keyframes[a];
keyframeValues[i][a] = keyframes[a].value;
}
}
}
//And the code to modify the animation data
void SliderListener()
{
keyframedata[0][0].value = keyframeValues[0][0] + HeightSlider.value;
keyframedata[0][2].value = keyframeValues[0][2] + HeightSlider.value;
CopyAnimationClip();
}
//The code to save animation to file
void SaveAnimationToFile(string path)
{
for (int i = 0; i < RelativePath.Length; i++)
{
//The animation data file is the file to store animation data like keyframes;
string animationdatafilepath = path + "/" + RelativePath[i] + "/" + propertyName[i] + ".txt";
if (File.Exists(animationdatafilepath))
{
//If the file already exists, delete and create new one.
File.Delete(animationdatafilepath);
Debug.Log("Already have a file with same name, overwrite");
}
using (StreamWriter sw = File.CreateText(animationdatafilepath))
{
sw.WriteLine(RelativePath[i]);//Write the relative path of the transform
propertyName[i] = propertyName[i].Replace("m_", "");
sw.WriteLine(propertyName[i]);//Write the property name of the transform
sw.WriteLine(keyframedata[i].Length);//Write how many keyframes are there in the curve (so when loading the program knows how many to expect)
for (int c = 0; c < keyframedata[i].Length; c++)
{
sw.WriteLine(keyframedata[i][c].time.ToString("F7") + ","//Keep 7 decimals, that is almost the maximum accurate for float
+ keyframedata[i][c].value.ToString("F7") + ","
+ keyframedata[i][c].inTangent.ToString("F7") + ","
+ keyframedata[i][c].outTangent.ToString("F7") + ","
+ keyframedata[i][c].weightedMode + ","
+ keyframedata[i][c].inWeight.ToString("F7") + ","
+ keyframedata[i][c].outWeight.ToString("F7"));
}
}
Debug.Log("File has been created at " + animationdatafilepath);
}
}