Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

AnimationUtility.SetEditorCurve can't add Curve with one keyfram

Discussion in 'Editor & General Support' started by nicloay, May 22, 2014.

  1. nicloay

    nicloay

    Joined:
    Jul 11, 2012
    Posts:
    540
    I have following code
    Code (csharp):
    1.  
    2. AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalPosition.x") ,curveX);
    3.  
    And it works well for curves where there more than 1 keyframe, but when I call this method with just one keyframe, i'm getting this

    Code (csharp):
    1.  
    2. Key count: 1 on curve 'Skeleton/Kevin_body/upperbody/Hand_l/elbow_L/hand_l'
    3. UnityEditor.AnimationUtility:SetEditorCurve(AnimationClip, EditorCurveBinding, AnimationCurve)
    4. UnitySpineImporter.SpineUtil:addBoneAnimationToClip(AnimationClip, Dictionary`2, SpineData, Dictionary`2, Single) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:740)
    5. UnitySpineImporter.SpineUtil:addAnimation(GameObject, String, SpineData, Dictionary`2, AttachmentGOByNameBySlot, Int32, ModelImporterAnimationType, Boolean) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:413)
    6. UnitySpineImporter.SpineImporterWizard:OnWizardCreate() (at Assets/UnitySpineImporter/Scripts/Editor/SpineImporterWizard.cs:75)
    7. UnityEditor.HostView:OnGUI()
    8.  
    9. Index (1) is out of range [0, 1)
    10. UnityEditor.AnimationUtility:SetEditorCurve(AnimationClip, EditorCurveBinding, AnimationCurve)
    11. UnitySpineImporter.SpineUtil:addBoneAnimationToClip(AnimationClip, Dictionary`2, SpineData, Dictionary`2, Single) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:740)
    12. UnitySpineImporter.SpineUtil:addAnimation(GameObject, String, SpineData, Dictionary`2, AttachmentGOByNameBySlot, Int32, ModelImporterAnimationType, Boolean) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:413)
    13. UnitySpineImporter.SpineImporterWizard:OnWizardCreate() (at Assets/UnitySpineImporter/Scripts/Editor/SpineImporterWizard.cs:75)
    14. UnityEditor.HostView:OnGUI()
    15.  
    16. Index (-1) is out of range [0, 1)
    17. UnityEditor.AnimationUtility:SetEditorCurve(AnimationClip, EditorCurveBinding, AnimationCurve)
    18. UnitySpineImporter.SpineUtil:addBoneAnimationToClip(AnimationClip, Dictionary`2, SpineData, Dictionary`2, Single) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:740)
    19. UnitySpineImporter.SpineUtil:addAnimation(GameObject, String, SpineData, Dictionary`2, AttachmentGOByNameBySlot, Int32, ModelImporterAnimationType, Boolean) (at Assets/UnitySpineImporter/Scripts/Editor/Util/SpineUtil.cs:413)
    20. UnitySpineImporter.SpineImporterWizard:OnWizardCreate() (at Assets/UnitySpineImporter/Scripts/Editor/SpineImporterWizard.cs:75)
    21. UnityEditor.HostView:OnGUI()
    22.  
    Is there any workaround?
    I use 4.3.4f1 version.
     
  2. Osntear

    Osntear

    Joined:
    Nov 14, 2014
    Posts:
    4
    I have the same issue. The unity throw many errors when I build, but that work so ok. Why ?
    And one thing, I use "Blending" in Spine, so when I build into Unity, that "Blending" don't appear, some one tell me why ?
    Thanks so much !
     
  3. TheoTowers

    TheoTowers

    Joined:
    May 8, 2013
    Posts:
    19
    Anyone seeing this in 2019? I'm finding I'm able to set the Editor Curves, but not without generating two errors.

    Here's my code:

    Code (CSharp):
    1. Keyframe[] keys = new Keyframe[1] { new Keyframe(0, myFloatValue) };
    2.             AnimationCurve animationCurve = new AnimationCurve(keys);
    3.  
    4.             AnimationUtility.SetEditorCurve(animationClip, curveBinding, animationCurve);
    And here are the errors I get:

    Key index (1) is out of range [0, 1)
    UnityEditor.AnimationUtility:SetEditorCurve(AnimationClip, EditorCurveBinding, AnimationCurve)
    SnapshotCreatorEditor:RecordKeyframe() (at Assets/Scripts/Snapshot System/Editor/SnapshotCreatorEditor.cs:431)
    SnapshotCreatorEditor:OnNewSnapshotBtnClicked() (at Assets/Scripts/Snapshot System/Editor/SnapshotCreatorEditor.cs:390)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)

    Key index (-1) is out of range [0, 1)
    UnityEditor.AnimationUtility:SetEditorCurve(AnimationClip, EditorCurveBinding, AnimationCurve)
    SnapshotCreatorEditor:RecordKeyframe() (at Assets/Scripts/Snapshot System/Editor/SnapshotCreatorEditor.cs:431)
    SnapshotCreatorEditor:OnNewSnapshotBtnClicked() (at Assets/Scripts/Snapshot System/Editor/SnapshotCreatorEditor.cs:390)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)

    Again, the EditorCurve does get successfully set, but these errors are definitely not ideal. I can't even hide them with a Try-Catch because they are internal.
     
  4. TheoTowers

    TheoTowers

    Joined:
    May 8, 2013
    Posts:
    19
    It turns out this is only happening when it gets to this curve binding:

    (UnityEngine.Transform) m_LocalRotation.w

    There's something it hates about the w component of the object's orientation. But what?
     
  5. UScripter

    UScripter

    Joined:
    Jul 26, 2014
    Posts:
    12
    I know I'm reviving an old thread, but I figured out a solution (or a workaround) that fixes this problem. I thought I should share it so that other people that stumble upon this issue don't have to go through what I went through. I still don't know why this issue happens, but here is my original code:
    Code (CSharp):
    1.  
    2.     public override void SetAnimationCurves(AnimationClip clip)
    3.     {
    4.         AnimationCurve curveRotX = keyframesRotX.GenerateCurve(); # Some function in some object that generates an animation curve
    5.         AnimationCurve curveRotY = keyframesRotY.GenerateCurve(); # Some function in some object that generates an animation curve
    6.         AnimationCurve curveRotZ = keyframesRotZ.GenerateCurve(); # Some function in some object that generates an animation curve
    7.         AnimationCurve curveRotW = keyframesRotW.GenerateCurve(); # Some function in some object that generates an animation curve
    8.  
    9.         if (curveRotX != null) clip.SetCurve(path, typeof(Transform), "m_LocalRotation.x", curveRotX);
    10.         if (curveRotY != null) clip.SetCurve(path, typeof(Transform), "m_LocalRotation.y", curveRotY);
    11.         if (curveRotZ != null) clip.SetCurve(path, typeof(Transform), "m_LocalRotation.z", curveRotZ);
    12.         if (curveRotW != null) clip.SetCurve(path, typeof(Transform), "m_LocalRotation.w", curveRotW);
    13.     }
    Using this code instead fixes the problem:
    Code (CSharp):
    1.  
    2.     public override void SetAnimationCurves(AnimationClip clip)
    3.     {
    4.         AnimationCurve curveRotX = keyframesRotX.GenerateCurve(); # Some function in some object that generates an animation curve
    5.         AnimationCurve curveRotY = keyframesRotY.GenerateCurve(); # Some function in some object that generates an animation curve
    6.         AnimationCurve curveRotZ = keyframesRotZ.GenerateCurve(); # Some function in some object that generates an animation curve
    7.         AnimationCurve curveRotW = keyframesRotW.GenerateCurve(); # Some function in some object that generates an animation curve
    8.  
    9.         int maxCurveLength = Mathf.Max(curveRotX.length,
    10.             curveRotY.length, curveRotZ.length, curveRotW.length);
    11.  
    12.         if (curveRotX != null && curveRotX.length != maxCurveLength)
    13.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.x", curveRotX);
    14.         if (curveRotY != null && curveRotY.length != maxCurveLength)
    15.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.y", curveRotY);
    16.         if (curveRotZ != null && curveRotZ.length != maxCurveLength)
    17.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.z", curveRotZ);
    18.         if (curveRotW != null && curveRotW.length != maxCurveLength)
    19.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.w", curveRotW);
    20.  
    21.         if (curveRotX != null && curveRotX.length == maxCurveLength)
    22.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.x", curveRotX);
    23.         if (curveRotY != null && curveRotY.length == maxCurveLength)
    24.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.y", curveRotY);
    25.         if (curveRotZ != null && curveRotZ.length == maxCurveLength)
    26.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.z", curveRotZ);
    27.         if (curveRotW != null && curveRotW.length == maxCurveLength)
    28.             clip.SetCurve(path, typeof(Transform), "m_LocalRotation.w", curveRotW);
    29.     }
    The main difference is that the curve(s) with the biggest number of keyframes are set last. It's weird that this solves the issue, but it does. This is also the case with position curves. I would've submitted a bug report, but I can't recreate the issue in a clean project (because I have a lot of code that records those animations at runtime at different timeScales).

    Edit:
    After a bit more experimentation, it turns out the the calls to
    SetCurve
    need to be called in ascending order (by keyframe count) or the errors might still occur. I updated the code to do that, and now the errors never occur:
    Code (CSharp):
    1.  
    2.     public override void SetAnimationCurves(AnimationClip clip)
    3.     {
    4.         Tuple<AnimationCurve, string>[] curves = new Tuple<AnimationCurve, string>[] {
    5.             new Tuple<AnimationCurve, string>
    6.                 (keyframesRotX.GenerateCurve(), "m_LocalRotation.x"),
    7.             new Tuple<AnimationCurve, string>
    8.                 (keyframesRotY.GenerateCurve(), "m_LocalRotation.y"),
    9.             new Tuple<AnimationCurve, string>
    10.                 (keyframesRotZ.GenerateCurve(), "m_LocalRotation.z"),
    11.             new Tuple<AnimationCurve, string>
    12.                 (keyframesRotW.GenerateCurve(), "m_LocalRotation.w")
    13.         };
    14.  
    15.         Array.Sort(curves, new Comparison<Tuple<AnimationCurve, string>>(
    16.                   (i1, i2) =>
    17.                   {
    18.                       int len1 = i1.Item1 == null ? 0 : i1.Item1.length;
    19.                       int len2 = i2.Item1 == null ? 0 : i2.Item1.length;
    20.                       return len1.CompareTo(len2);
    21.                   }));
    22.  
    23.         foreach (var curve in curves)
    24.             if (curve.Item1 != null)
    25.                 clip.SetCurve(path, typeof(Transform), curve.Item2, curve.Item1);
    26.     }
    Another edit:
    After a bit more testing, it turns out that the error still occurs (much less frequently though). I'll ignore it because it doesn't affect the gameplay, but if anyone knows how to solve this I'd be grateful.
     
    Last edited: Jun 23, 2020
    unity_lt2okwhid7 and npatch like this.
  6. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    I just hit the same issue. I'm trying to simplify curves before adding them to an animation clip and I was getting the same issue.
    Your code indeed eliminates the most of them but I still get some of the same flavor.
    Also I bet that these, in turn, cause the assertion errors I get afterwards when calling EnsureQuaternionContinuity, after having set all curves in a clip.
     
  7. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    Ok I found sth out which ironed out another issue. Primary Animation.SetKeyLeftTangentMode(and right equivalent) and but quite probably also AnimationClip.EnsureQuaternionContinuity, mess with the curve keyframe length. I just noticed one curve was throwing the same Index X+1 is out of range of [0,X) and I noticed that when I created the animation curve (using the constructor that takes a Keyframe[]) the length of the Keyframe[] and the curve.length were the same. After the first iteration which called SetKeyLeftTangentMode and SetKeyRightTangentMode on the first key, the curve.length got reduced. I guess they are changing the tangent which sometimes causes keyframe reduction.

    Problem was that I was using the Keyframe[] length as the limit for the loop. When I changed that to curve.length, the error went away. Possibly this is just one edge case though.