Search Unity

Reduce animationclip length

Discussion in 'Editor & General Support' started by Morning, Apr 8, 2012.

  1. Morning

    Morning

    Joined:
    Feb 4, 2012
    Posts:
    1,141
    I made a simple animation in the unity animation editor but for some weird reasons it has this tail in the end that I have no idea how to remove. I tried google, tried doc, can't find any info on this.
    This is a mild case. I once got a tail that was almost half the length of my animation which really screwed things up.


    I feel ashamed for such basic questions but what else can I do?
     
  2. alstonc99

    alstonc99

    Joined:
    Mar 19, 2012
    Posts:
    2
    I found the problem is caused by the data of "m_LocalEulerAnglesHint" in the *.anim files.
    You must convert the *.anim assets to text format and delete the redundant data manually.

    Here are the codes I write to do that:
    Code (csharp):
    1.  
    2. #include <windows.h>
    3. #include <iostream>
    4. #include <fstream>
    5. #include <string>
    6. #include <list>
    7.  
    8. using namespace std;
    9.  
    10. list<string> lines;
    11. typedef list<string>::iterator linesit;
    12. list<linesit> marks;
    13.  
    14. void LoadAnim(const string name)
    15. {
    16.     lines.clear();
    17.     marks.clear();
    18.  
    19.     ifstream ifs(name.c_str(), ifstream::in);
    20.  
    21.     string str;
    22.     if(getline(ifs, str))
    23.     {
    24.         if( str[0] == '%'  
    25.             str[1] == 'Y'  
    26.             str[2] == 'A'  
    27.             str[3] == 'M'  
    28.             str[4] == 'L')
    29.         {
    30.             lines.push_back(str);
    31.             while(getline(ifs, str))
    32.             {
    33.                 lines.push_back(str);
    34.  
    35.                 if( str.find("m_LocalEulerAnglesHint") != string::npos)
    36.                 {
    37.                     linesit lit = lines.end();
    38.                     --lit;
    39.                     marks.push_back(lit);
    40.                 }
    41.             }
    42.         }
    43.     }
    44.     //cout<<marks.size()<<endl;
    45. }
    46.  
    47. int CountLeadingSpace(const string str)
    48. {
    49.     int len = str.length();
    50.     int count = 0;
    51.  
    52.     for(; count < len; ++count)
    53.     {
    54.         if(str[count] != ' ') break;
    55.     }
    56.  
    57.     return count;
    58. }
    59.  
    60. void RemoveErrorData(linesit lit)
    61. {
    62.     int litls = CountLeadingSpace(*lit);
    63.  
    64.     //find first
    65.     linesit prev = lit;
    66.     int prevls;
    67.     do
    68.     {
    69.         --prev;
    70.         prevls = CountLeadingSpace(*prev);
    71.     }
    72.     while(prevls >= litls);
    73.  
    74.     //find last
    75.     linesit next = lit;
    76.     int nextls;
    77.     do
    78.     {
    79.         ++next;
    80.         nextls = CountLeadingSpace(*next);
    81.     }
    82.     while(nextls >= litls);
    83.  
    84.     //remove first to last
    85.     do
    86.     {
    87.         prev = lines.erase(prev);
    88.     }
    89.     while(prev != next);
    90. }
    91.  
    92. void RemoveAllErrorData()
    93. {
    94.     list<linesit>::iterator it = marks.begin();
    95.     for(; it != marks.end(); ++it)
    96.     {
    97.         RemoveErrorData(*it);
    98.     }
    99. }
    100.  
    101. void SaveAnim(const string name)
    102. {
    103.     ofstream ofs(name.c_str(), ofstream::out | ofstream::trunc | ofstream::binary);
    104.  
    105.     list<string>::iterator it = lines.begin();
    106.     for(; it != lines.end(); ++it)
    107.     {
    108.         ofs << (*it);
    109.         ofs << char(0x0A);
    110.     }
    111. }
    112.  
    113. int main()
    114. {
    115.     LARGE_INTEGER filesize;
    116.     WIN32_FIND_DATA ffd;
    117.     TCHAR szDir[] = "*.anim";
    118.     HANDLE hFind = INVALID_HANDLE_VALUE;
    119.     DWORD dwError=0;
    120.  
    121.     hFind = FindFirstFile(szDir, &ffd);
    122.  
    123.     if (INVALID_HANDLE_VALUE == hFind)
    124.     {
    125.         //not found
    126.         return 0;
    127.     }
    128.  
    129.     do
    130.     {
    131.         if (ffd.dwFileAttributes  FILE_ATTRIBUTE_DIRECTORY)
    132.         {
    133.         //_tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
    134.         }
    135.         else
    136.         {
    137.             filesize.LowPart = ffd.nFileSizeLow;
    138.             filesize.HighPart = ffd.nFileSizeHigh;
    139.             //printf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
    140.  
    141.             //cout<<marks.size()<<endl;
    142.  
    143.             LoadAnim(ffd.cFileName);
    144.             if( !marks.empty() )
    145.             {
    146.                 printf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
    147.  
    148.                 RemoveAllErrorData();
    149.                 SaveAnim(ffd.cFileName);
    150.             }
    151.         }
    152.     }
    153.     while (FindNextFile(hFind, &ffd) != 0);
    154.  
    155.     return 0;
    156. }
    157.  
    158.  
     
  3. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    I can't really understand where is the problem... have you set the LOOP function on?
    If so, then of course it shows you how the anim proceeds after the keyframes.
    Otherwise I've never seen anything similar and I wonder how you managed to do that.
    Sorry but the image is really not clear on what's happening.
     
  4. RElam

    RElam

    Joined:
    Nov 16, 2009
    Posts:
    375
    Yea, I have had this happen as well, very annoying. Not sure what causes it, but it basically creates an erroneous length at end of animation and you can't fix it through UI as there are no keyframes causing it.
     
  5. tenfour

    tenfour

    Joined:
    Jan 3, 2012
    Posts:
    7
    I have had the same problem. This seems to be a bug. I think Unity 3.4 had an option to clean up the end of the clip, but it's gone now!
     
    Last edited: May 7, 2012
  6. RichMakeGame

    RichMakeGame

    Joined:
    May 8, 2012
    Posts:
    12
    I am also reporting this bug.

    You can reliably recreate it by animating a hierarchy. Note the bug only occurs (for me) on *children of children of the animated parent*
    so:
    *animated object*
    ----child
    ---------child with animation problem

    once you add two keyframes to the 'problem child' and drag the timeline beyond the last keyframe, the animation will permanently be changed in length to the timeline scrubber position. Extremely annoying bug.
     
  7. athyri

    athyri

    Joined:
    Jan 19, 2012
    Posts:
    10
    alstonc99, how do you convert the *.anim assets to text format (and back)?
     
  8. igor_giv

    igor_giv

    Joined:
    Dec 21, 2011
    Posts:
    3
    You need to switch to 'Force Text' asset serialization mode in Unity (Edit -> Project Settings -> Editor -> Asset Serialization Mode).
    You have to have Unity Pro license by the way...
    I am going to try the code snippet provided by alstonc99 - hopefully it will help me to cut off the tail.
     
  9. igor_giv

    igor_giv

    Joined:
    Dec 21, 2011
    Posts:
    3
    It is incredible but it did work!!! Thanks a lot alstonc99!
     
  10. RichMakeGame

    RichMakeGame

    Joined:
    May 8, 2012
    Posts:
    12
    how do you run the script on an asset? do you use that from inside unity?

    Even with the fix though this is an extremely annoying bug. It's so easy to break the animation again while editing it
     
  11. igor_giv

    igor_giv

    Joined:
    Dec 21, 2011
    Posts:
    3
    No. I just created a VC++ console project in Visual Studio, pasted his code (with minor corrections) and just pointed it to the directory with animations (within Assets folder). It worked like a charm.
     
  12. RichMakeGame

    RichMakeGame

    Joined:
    May 8, 2012
    Posts:
    12
    can anyone think of a solution to remove this data without visual studio :/ I'm an artist mainly
     
  13. Helmut Duregger

    Helmut Duregger

    Joined:
    Mar 17, 2010
    Posts:
    18
    Thanks to alstonc99 for sharing the solution. We made a Unity Editor script out of it, the usage explanation contains:

    Code (csharp):
    1.  
    2. Provides a Unity Editor function that 'fixes' the animation length on selected AnimationClip assets.
    3. You can also select directories to process the animations inside.
    4.  
    5. It adds the menu entry "Fix Animation Length" to the Assets menu. You can also access it when right
    6. clicking on the Project view. Hence, you can select assets in the Project view and right click -> fix.
    7.  
    8. The assets need to be saved in order for this to work. Thus, the script saves all assets before commencing.
    9.  
    10. Based on alstonc99's script at http://forum.unity3d.com/threads/131340-Reduce-animationclip-length.
    11. Thanks for finding the solution and sharing it.
    12.  
    13. This script is in the public domain, feel free to improve and share.
    14.  
    15. NOTE: Unity seems to cache the selected assets. If you select all your assets and run this script, Unity
    16.      might hang for a few seconds. Afterwards processing all your assets again is faster.
    17.    
    18. DISCLAIMER: We currently don't know what purpose the bogus entry serves. Use at your own risk!
    19.  
    Here is the script:

    Code (csharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.IO;
    4. using System.Collections.Generic;
    5. using System;
    6.  
    7. /// <summary>
    8. /// Provides a Unity Editor function that 'fixes' the animation length on selected AnimationClip assets.
    9. /// You can also select directories to process the animations inside.
    10. ///
    11. /// It adds the menu entry "Fix Animation Length" to the Assets menu. You can also access it when right
    12. /// clicking on the Project view. Hence, you can select assets in the Project view and right click -> fix.
    13. ///
    14. /// The assets need to be saved in order for this to work. Thus, the script saves all assets before commencing.
    15. ///
    16. /// Based on alstonc99's script at http://forum.unity3d.com/threads/131340-Reduce-animationclip-length.
    17. /// Thanks for finding the solution and sharing it.
    18. ///
    19. /// This script is in the public domain, feel free to improve and share.
    20. ///
    21. /// NOTE: Unity seems to cache the selected assets. If you select all your assets and run this script, Unity
    22. ///       might hang for a few seconds. Afterwards processing all your assets again is faster.
    23. ///      
    24. /// DISCLAIMER: We currently don't know what purpose the bogus entry serves. Use at your own risk!
    25. /// </summary>
    26.  
    27. public static class FixAnimationLength
    28. {
    29.     private const SelectionMode selectionMode   = SelectionMode.Assets |
    30.                                                   SelectionMode.DeepAssets |
    31.                                                   SelectionMode.TopLevel |
    32.                                                   SelectionMode.ExcludePrefab;
    33.  
    34.     private const string        tokenToReplace  = "m_LocalEulerAnglesHint";
    35.     private const string        replacement     = "REMOVE_ME_LocalEulerAnglesHint";
    36.  
    37.  
    38.     [MenuItem( "Assets/Fix Animation Length" )]
    39.     public static void RemoveLocalEulerAnglesHints()
    40.     {
    41.         Debug.Log( "Marking the '" + tokenToReplace + "' entries in the selected AnimationClips with '" + replacement + "'.\n" +
    42.                    "Open the animations in the animation editor of Unity to provide the 'Clean Up Leftover curves' button. " +
    43.                    "Click on the button and confirm the dialog to finally fix the animation." );
    44.  
    45.         AssetDatabase.SaveAssets();
    46.  
    47.         string s = "";
    48.  
    49.         foreach ( AnimationClip animationClip in Selection.GetFiltered( typeof( AnimationClip ), selectionMode ) )
    50.         {
    51.             var path = AssetDatabase.GetAssetPath( animationClip );
    52.  
    53.             var changed = Fix( path );
    54.  
    55.             if ( changed )
    56.             {
    57.                 s += "Processed\t'" + path + "'\n";
    58.             }
    59.             else
    60.             {
    61.                 s += "Skipped\t\t'" + path + "'\n";
    62.             }
    63.         }
    64.  
    65.         AssetDatabase.Refresh();
    66.  
    67.         Debug.Log( s );
    68.         Debug.Log( "Done." );
    69.     }
    70.  
    71.     private static bool Fix( string path )
    72.     {
    73.         List<string> lines = new List<string>();
    74.  
    75.         bool changed = false;
    76.  
    77.         using ( var reader = new StreamReader( path ) )
    78.         {
    79.             var line = reader.ReadLine();
    80.  
    81.             while ( !String.IsNullOrEmpty( line ) )
    82.             {
    83.                 changed = changed || line.Contains( tokenToReplace );
    84.  
    85.                 // Replace the entry if it is in this line
    86.                 line = line.Replace( tokenToReplace, replacement );
    87.  
    88.                 lines.Add( line );
    89.  
    90.                 line = reader.ReadLine();
    91.             }
    92.         }
    93.  
    94.         // Only write the file if it actually changed
    95.         if ( changed )
    96.         {
    97.             using ( var writer = new StreamWriter( path ) )
    98.             {
    99.                 foreach ( var line in lines )
    100.                 {
    101.                     writer.WriteLine( line );
    102.                 }
    103.             }
    104.         }
    105.  
    106.         return changed;
    107.     }
    108. }
    109.  
    110.  
    Cheers,

    Helmut
     
    Last edited: May 16, 2012
  14. RichMakeGame

    RichMakeGame

    Joined:
    May 8, 2012
    Posts:
    12
    amazing, thanks for posting!

    I'm not afraid to admit I'm pretty much a noob at unity at this point.. can I ask how do I install editor functions like this?
    cheers!

    EDIT: aha! ok after digging around, I figured it out: Create a new C# script in a folder named 'Editor' within Assets, and paste in. Unity does the rest, fantastic :)
     
    Last edited: May 16, 2012
  15. athyri

    athyri

    Joined:
    Jan 19, 2012
    Posts:
    10
    thanks helmut!

    do i still need to switch to 'Force Text' asset serialization mode with this script?
     
  16. alstonc99

    alstonc99

    Joined:
    Mar 19, 2012
    Posts:
    2
    Another method to fix this problem, this doesn't need text-format assets.

    Create a C# script file in Assets/Editor/FixAnimationWindow.cs and paste the code to the file.
    Then run Unity, there will be a new menuitem "Tools/FixAnimation" in the menubar.

    Click the menuitem will show a "FixAnimation" window.
    Select a gameobject you want to fix and click "Fix Animation Length" on the tool window,
    the AnimationClip will be fixed.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public class FixAnimationWindow : EditorWindow
    8. {
    9.     List<Animation> m_animations = new List<Animation>();
    10.     Object[] m_oldObjects = null;
    11.     System.DateTime m_lastFrameTime;
    12.     float m_totalTime = 0f;
    13.  
    14.     [MenuItem("Tools/FixAnimation", false, 0)]
    15.     static void Init()
    16.     {
    17.         //create new window
    18.        EditorWindow.GetWindow<FixAnimationWindow>(false, "FixAnimation", true);
    19.     }
    20.  
    21.     void OnInspectorUpdate()
    22.     {
    23.         this.Repaint();
    24.     }
    25.  
    26.     void OnSelectionChange()
    27.     {
    28.         m_animations.Clear();
    29.  
    30.         if( Selection.activeGameObject == null )
    31.         {
    32.             return;
    33.         }
    34.  
    35.         foreach(GameObject go in Selection.gameObjects)
    36.         {
    37.             Animation ani = go.GetComponent<Animation>();
    38.             if(ani)
    39.             {
    40.                 AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    41.                 if(clips.Length > 0)
    42.                 {
    43.                     m_animations.Add(ani);
    44.                 }
    45.             }
    46.         }
    47.     }
    48.  
    49.     void OnGUI()
    50.     {
    51.         if(Selection.activeGameObject != null  m_animations.Count == 0)
    52.         {
    53.             OnSelectionChange();
    54.         }
    55.  
    56.         if(Selection.activeGameObject == null || m_animations.Count == 0)
    57.         {
    58.             GUILayout.Label( "Must select one GameObject with Animation" );
    59.             return;
    60.         }
    61.  
    62.         GUILayout.Label( string.Format("You selected {0} animation(s)", m_animations.Count ) );
    63.  
    64.         if(GUILayout.Button("Fix Animation Length"))
    65.         {
    66.             Fix();
    67.         }
    68.     }
    69.  
    70.     // Update is called once per frame
    71.     void Update ()
    72.     {
    73.         //re-select old objects to force repainting AnimationWindow
    74.         if(m_oldObjects != null)
    75.         {
    76.             m_totalTime += (float)System.DateTime.Now.Subtract(m_lastFrameTime).TotalSeconds;
    77.             m_lastFrameTime = System.DateTime.Now;
    78.  
    79.             if(m_totalTime >= 0.1f)
    80.             {
    81.                 Selection.objects = m_oldObjects;
    82.                 m_oldObjects = null;
    83.             }
    84.         }
    85.     }
    86.  
    87.     void Fix()
    88.     {
    89.         foreach(Animation ani in m_animations)
    90.         {
    91.             AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    92.             foreach(AnimationClip clip in clips)
    93.             {
    94.                 if(clip)
    95.                 {
    96.                     AnimationUtility.SetEditorCurve(clip, "", typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.x", null);
    97.                     AnimationUtility.SetEditorCurve(clip, "", typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.y", null);
    98.                     AnimationUtility.SetEditorCurve(clip, "", typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.z", null);
    99.                 }
    100.             }
    101.         }
    102.  
    103.         if(AnimationUtility.InAnimationMode())
    104.         {
    105.             AnimationUtility.StopAnimationMode();
    106.         }
    107.         else
    108.         {
    109.             //re-select objects to force repainting AnimationWindow
    110.             m_oldObjects = Selection.objects;
    111.             Selection.objects = new Object[0];
    112.             m_lastFrameTime = System.DateTime.Now;
    113.             m_totalTime = 0;
    114.         }
    115.  
    116.     }
    117. }
    118.  
     
  17. KlaRo115

    KlaRo115

    Joined:
    Feb 24, 2006
    Posts:
    675
    Nope, none of these is working for me... :S
     
  18. lugehorsam

    lugehorsam

    Joined:
    Jun 3, 2012
    Posts:
    9
    Alstonic, thanks for the code. Where can I find this Assets/Editor/etc... folder to stick the code in? I see many assets folders on my computer for unity, but none that contain an "Editor" subfolder.
     
  19. lugehorsam

    lugehorsam

    Joined:
    Jun 3, 2012
    Posts:
    9
    Doh, I'm a dope. I just fixed the issue (I made the editor folder myself.) Alstonc this is so amazing, thank you so much.
     
  20. Brazen-Artifice

    Brazen-Artifice

    Joined:
    Jun 14, 2012
    Posts:
    1
    Brilliant - worked perfectly! I'm ten pages from the end of a 400 page book on Unity for beginners, and this is the only thing that stumped me. How lucky for me that you've solved it only 3 weeks before I got stuck.

    I put created the Editor folder in the Assets folder of the project I was having trouble with. I wonder if it's possible to put it somewhere so it will be available in _all_ my projects?

    Thanks so much.
     
  21. athyri

    athyri

    Joined:
    Jan 19, 2012
    Posts:
    10
    works like a charm, thanks alot alstonc99!
     
  22. Rob1508

    Rob1508

    Joined:
    Jun 25, 2012
    Posts:
    17
    It does not work for me? I got the Tools menu but if I select the GO with the incorrect animation and hit "Fix animation length" nothing happens. Unity deselects and selects the GO again automatically but thats all..

    I'm on Unity (not Pro) 3.5.2f2, the newest version.
     
  23. Rob1508

    Rob1508

    Joined:
    Jun 25, 2012
    Posts:
    17
    I modified the script. Now it is working with the newest Unity version (Free, 3.5.2f2)!


    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. using UnityEditor;
    5.  
    6. using System.Collections;
    7.  
    8. using System.Collections.Generic;
    9.  
    10. public class FixAnimationWindow : EditorWindow
    11.  
    12. {
    13.  
    14.     List<Animation> m_animations = new List<Animation>();
    15.  
    16.     Object[] m_oldObjects = null;
    17.  
    18.     System.DateTime m_lastFrameTime;
    19.  
    20.     float m_totalTime = 0f;
    21.  
    22.     int cIndex = 0;
    23.  
    24.     [MenuItem("Tools/FixAnimation", false, 0)]
    25.  
    26.     static void Init()
    27.  
    28.     {
    29.  
    30.         //create new window
    31.  
    32.        EditorWindow.GetWindow<FixAnimationWindow>(false, "FixAnimation", true);
    33.  
    34.     }
    35.  
    36.     void OnInspectorUpdate()
    37.  
    38.     {
    39.  
    40.         this.Repaint();
    41.  
    42.     }
    43.  
    44.     void OnSelectionChange()
    45.  
    46.     {
    47.  
    48.         m_animations.Clear();
    49.  
    50.         if( Selection.activeGameObject == null )
    51.  
    52.         {
    53.  
    54.             return;
    55.  
    56.         }
    57.  
    58.         foreach(GameObject go in Selection.gameObjects)
    59.  
    60.         {
    61.  
    62.             Animation ani = go.GetComponent<Animation>();
    63.  
    64.             if(ani)
    65.  
    66.             {
    67.  
    68.                 AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    69.  
    70.                 if(clips.Length > 0)
    71.  
    72.                 {
    73.  
    74.                     m_animations.Add(ani);
    75.  
    76.                 }
    77.  
    78.             }
    79.  
    80.         }
    81.  
    82.     }
    83.  
    84.     void OnGUI()
    85.  
    86.     {
    87.  
    88.         if(Selection.activeGameObject != null  m_animations.Count == 0)
    89.  
    90.         {
    91.  
    92.             OnSelectionChange();
    93.  
    94.         }
    95.  
    96.         if(Selection.activeGameObject == null || m_animations.Count == 0)
    97.  
    98.         {
    99.  
    100.             GUILayout.Label( "Must select one GameObject with Animation" );
    101.  
    102.             return;
    103.  
    104.         }
    105.  
    106.         GUILayout.Label( string.Format("You selected {0} animation(s)", m_animations.Count ) );
    107.  
    108.         if(GUILayout.Button("Fix Animation Length"))
    109.  
    110.         {
    111.  
    112.             Fix();
    113.  
    114.         }
    115.  
    116.     }
    117.  
    118.     // Update is called once per frame
    119.  
    120.     void Update ()
    121.  
    122.     {
    123.  
    124.         //re-select old objects to force repainting AnimationWindow
    125.  
    126.         if(m_oldObjects != null)
    127.  
    128.         {
    129.  
    130.             m_totalTime += (float)System.DateTime.Now.Subtract(m_lastFrameTime).TotalSeconds;
    131.  
    132.             m_lastFrameTime = System.DateTime.Now;
    133.  
    134.             if(m_totalTime >= 0.1f)
    135.  
    136.             {
    137.  
    138.                 Selection.objects = m_oldObjects;
    139.  
    140.                 m_oldObjects = null;
    141.  
    142.             }
    143.  
    144.         }
    145.  
    146.     }
    147.  
    148.     void Fix()
    149.  
    150.     {
    151.  
    152.         foreach(Animation ani in m_animations)
    153.  
    154.         {
    155.  
    156.             AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    157.  
    158.             foreach(AnimationClip clip in clips)
    159.  
    160.             {
    161.  
    162.                 AnimationClipCurveData[] curves = AnimationUtility.GetAllCurves(clip);
    163.  
    164.                 foreach (AnimationClipCurveData currentCurveData in curves) {
    165.  
    166.                     string propName = currentCurveData.propertyName;
    167.                     if (propName == "m_LocalEulerAnglesHint.x") {
    168.                          AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.x", null);
    169.                         cIndex ++;
    170.  
    171.                     } else if (propName == "m_LocalEulerAnglesHint.y") {
    172.                          AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.y", null);
    173.                         cIndex ++;
    174.  
    175.                     } else if (propName == "m_LocalEulerAnglesHint.z") {
    176.                          AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.z", null);
    177.                         cIndex ++;
    178.  
    179.                     }
    180.  
    181.                 }
    182.  
    183.             }
    184.  
    185.             if (cIndex != 0) {
    186.  
    187.                 Debug.Log(cIndex + "false items cleared!");
    188.  
    189.             } else {
    190.  
    191.                 Debug.Log("Nothing to clear!");
    192.             }
    193.  
    194.         }
    195.  
    196.         if(AnimationUtility.InAnimationMode())
    197.  
    198.         {
    199.  
    200.             AnimationUtility.StopAnimationMode();
    201.  
    202.         }
    203.  
    204.         else
    205.  
    206.         {
    207.  
    208.             //re-select objects to force repainting AnimationWindow
    209.  
    210.             m_oldObjects = Selection.objects;
    211.  
    212.             Selection.objects = new Object[0];
    213.  
    214.             m_lastFrameTime = System.DateTime.Now;
    215.  
    216.             m_totalTime = 0;
    217.  
    218.         }
    219.  
    220.     }
    221.  
    222. }
    223.  
    Take a look at my new iOS Apps Unity Blog!
     
  24. Alexandar

    Alexandar

    Joined:
    Oct 30, 2012
    Posts:
    4
    Hi, I am new in this forum.

    I modified a little bit source code to be compatible with "gameobject" which have transform hierarchy.

    this code is available in only one gameobject selection. (sorry my english is not good.)


    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. using UnityEditor;
    5.  
    6. using System.Collections;
    7.  
    8. using System.Collections.Generic;
    9.  
    10.  
    11.  
    12. public class FixAnimationWindow : EditorWindow
    13.  
    14. {
    15.  
    16.     List<Animation> m_animations = new List<Animation>();
    17.     List<GameObject> m_selected_go = new List<GameObject>();
    18.  
    19.     Object[] m_oldObjects = null;
    20.  
    21.     System.DateTime m_lastFrameTime;
    22.  
    23.     float m_totalTime = 0f;
    24.  
    25.  
    26.  
    27.     [MenuItem("Tools/FixAnimation", false, 0)]
    28.  
    29.     static void Init()
    30.  
    31.     {
    32.  
    33.         //create new window
    34.  
    35.        EditorWindow.GetWindow<FixAnimationWindow>(false, "FixAnimation", true);
    36.  
    37.     }
    38.  
    39.  
    40.  
    41.     void OnInspectorUpdate()
    42.  
    43.     {
    44.  
    45.         this.Repaint();
    46.  
    47.     }
    48.  
    49.  
    50.  
    51.     void OnSelectionChange()
    52.  
    53.     {
    54.  
    55.         m_animations.Clear();
    56.  
    57.  
    58.  
    59.         if( Selection.activeGameObject == null )
    60.  
    61.         {
    62.  
    63.             return;
    64.  
    65.         }
    66.  
    67.  
    68.  
    69.         foreach(GameObject go in Selection.gameObjects)
    70.  
    71.         {
    72.             m_selected_go.Add (go);
    73.             Animation ani = go.GetComponent<Animation>();
    74.  
    75.             if(ani)
    76.  
    77.             {
    78.  
    79.                 AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    80.  
    81.                 if(clips.Length > 0)
    82.  
    83.                 {
    84.  
    85.                     m_animations.Add(ani);
    86.  
    87.                 }
    88.  
    89.             }
    90.  
    91.         }
    92.  
    93.     }
    94.  
    95.  
    96.  
    97.     void OnGUI()
    98.  
    99.     {
    100.  
    101.         if(Selection.activeGameObject != null  m_animations.Count == 0)
    102.  
    103.         {
    104.  
    105.             OnSelectionChange();
    106.  
    107.         }
    108.  
    109.  
    110.  
    111.         if(Selection.activeGameObject == null || m_animations.Count == 0)
    112.  
    113.         {
    114.  
    115.             GUILayout.Label( "Must select one GameObject with Animation" );
    116.  
    117.             return;
    118.  
    119.         }
    120.  
    121.  
    122.  
    123.         GUILayout.Label( string.Format("You selected {0} animation(s)", m_animations.Count ) );
    124.  
    125.  
    126.  
    127.         if(GUILayout.Button("Fix Animation Length"))
    128.  
    129.         {
    130.  
    131.             Fix();
    132.  
    133.         }
    134.  
    135.     }
    136.  
    137.  
    138.  
    139.     // Update is called once per frame
    140.  
    141.     void Update ()
    142.  
    143.     {
    144.  
    145.         //re-select old objects to force repainting AnimationWindow
    146.  
    147.         if(m_oldObjects != null)
    148.  
    149.         {
    150.  
    151.             m_totalTime += (float)System.DateTime.Now.Subtract(m_lastFrameTime).TotalSeconds;
    152.  
    153.             m_lastFrameTime = System.DateTime.Now;
    154.  
    155.  
    156.  
    157.             if(m_totalTime >= 0.1f)
    158.  
    159.             {
    160.  
    161.                 Selection.objects = m_oldObjects;
    162.  
    163.                 m_oldObjects = null;
    164.  
    165.             }
    166.  
    167.         }
    168.  
    169.     }
    170.  
    171.  
    172.  
    173.     void Fix()
    174.  
    175.     {
    176.  
    177.         foreach(Animation ani in m_animations)
    178.  
    179.         {
    180.  
    181.             AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    182.  
    183.             foreach(AnimationClip clip in clips)
    184.  
    185.             {
    186.  
    187.                 if(clip)
    188.  
    189.                 {
    190.                     AnimationClipCurveData[] curve_data = AnimationUtility.GetAllCurves(clip);                 
    191.                    
    192.                     FixLoop(clip,m_selected_go[0].transform,string.Empty);
    193.  
    194.                 }
    195.  
    196.             }
    197.  
    198.         }
    199.  
    200.  
    201.  
    202.         if(AnimationUtility.InAnimationMode())
    203.  
    204.         {
    205.  
    206.             AnimationUtility.StopAnimationMode();
    207.  
    208.         }
    209.  
    210.         else
    211.  
    212.         {
    213.  
    214.             //re-select objects to force repainting AnimationWindow
    215.  
    216.             m_oldObjects = Selection.objects;
    217.  
    218.             Selection.objects = new Object[0];
    219.  
    220.             m_lastFrameTime = System.DateTime.Now;
    221.  
    222.             m_totalTime = 0;
    223.  
    224.         }
    225.  
    226.  
    227.  
    228.     }
    229.    
    230.     void FixLoop(AnimationClip clip,Transform tr_parent, string parent_name){      
    231.         foreach(Transform tr in tr_parent){                    
    232.                        
    233.             AnimationUtility.SetEditorCurve(clip, parent_name + tr.name, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.x",null);
    234.    
    235.             AnimationUtility.SetEditorCurve(clip, parent_name + tr.name, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.y",null);
    236.    
    237.             AnimationUtility.SetEditorCurve(clip, parent_name + tr.name, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.z",null);
    238.            
    239.             FixLoop(clip,tr, parent_name + tr.name + "/");         
    240.         }
    241.     }
    242.  
    243. }
     
  25. Benproductions1

    Benproductions1

    Joined:
    May 11, 2011
    Posts:
    63
    Ok, so this exact problem is causing me some real problems and I REALLY need it fixed...

    But none of the scripts here work, either they screw up the file or produce a null reference exception...
    I really don't have the time to look through the code and fix it, so could someone plz post an update?

    Benproductions1
     
  26. johnnyt

    johnnyt

    Joined:
    Jun 20, 2013
    Posts:
    13
    Unity scripts won't function well if you change the version. Use the C++ code snippet instead.
     
  27. kevinlee98

    kevinlee98

    Joined:
    Jan 29, 2015
    Posts:
    1
    I solved this problem without coding.

    just put any empty event on the animation clip.

    that will be got fixed length for time duration that the event marked .
     
    Nido likes this.
  28. gordee

    gordee

    Joined:
    Mar 11, 2015
    Posts:
    1
    you dont need code. go into the dope sheet and there will be keyframe markers at the end delete them and all is fixed
     
    Nido likes this.
  29. Nido

    Nido

    Joined:
    Oct 21, 2013
    Posts:
    1
    Those last solutions are working on last Unity versions, not for that old versions of the moment they post.
     
  30. Logan76667

    Logan76667

    Joined:
    Dec 16, 2014
    Posts:
    1
    Almost been a year now, this bug still persists (Unity 5.3.1f1).
    None of the Scripts are working for me (getting the "Must select one GameObject with Animation" even though I selected a GameObject with the animation on it...) and there are no keyframe markers on the dopesheet or the curves as gordee suggested.
     
  31. Peacewise

    Peacewise

    Joined:
    Feb 27, 2014
    Posts:
    52
    Can confirm it is still a problem. I am experiencing this on Unity 5.6.0f3.

    I had an animation that went to 10 seconds, but then deleted all keyframes after 1 second. I wanted the animation to be 1 second, but it still thinks the animation is 10 seconds, with no keyframes after 1 second.

    Note that I did at one point delete ALL content from the animation, then recreate it from different bones with a different character hierarchy. I don't know if that affected anything in terms of leaving crud in the animation file. I've been creating these manually (not importing from anywhere). May just have to delete the animation and start over.

    Edit: An interesting note is that for a while, my animation timeline would not scroll back to 0 seconds. I wanted to add keyframes there, but had to zoom way out in the timeline for 0 seconds to appear. It was as if the animation thought that "zero" was further into the timeline.
     
    Last edited: May 21, 2017
  32. AbandonedCart

    AbandonedCart

    Joined:
    Mar 4, 2014
    Posts:
    72
    There was no reason to double the length of the file by double spacing everything (including the brackets). Ran into this issue while using assets purchased from the store that used models imported from 3dsMax.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class FixAnimationWindow : EditorWindow {
    7.  
    8.     List<Animation> m_animations = new List<Animation>();
    9.     Object[] m_oldObjects = null;
    10.     System.DateTime m_lastFrameTime;
    11.     float m_totalTime = 0f;
    12.     int cIndex = 0;
    13.  
    14.     [MenuItem("Tools/FixAnimation", false, 0)]
    15.  
    16.     static void Init() {
    17.         //create new window
    18.         EditorWindow.GetWindow<FixAnimationWindow>(false, "FixAnimation", true);
    19.     }
    20.  
    21.     void OnInspectorUpdate() {
    22.         this.Repaint();
    23.     }
    24.  
    25.     void OnSelectionChange() {
    26.         m_animations.Clear();
    27.         if( Selection.activeGameObject == null ) {
    28.             return;
    29.         }
    30.  
    31.         foreach(GameObject go in Selection.gameObjects) {
    32.             Animation ani = go.GetComponent<Animation>();
    33.             if(ani) {
    34.                 AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    35.                 if(clips.Length > 0) {
    36.                     m_animations.Add(ani);
    37.                 }
    38.             }
    39.         }
    40.     }
    41.  
    42.     void OnGUI() {
    43.         if(Selection.activeGameObject != null && m_animations.Count == 0) {
    44.             OnSelectionChange();
    45.         }
    46.  
    47.         if(Selection.activeGameObject == null || m_animations.Count == 0) {
    48.             GUILayout.Label( "Must select one GameObject with Animation" );
    49.             return;
    50.         }
    51.  
    52.         GUILayout.Label( string.Format("You selected {0} animation(s)", m_animations.Count ) );
    53.  
    54.         if(GUILayout.Button("Fix Animation Length")) {
    55.             Fix();
    56.         }
    57.     }
    58.  
    59.     // Update is called once per frame
    60.  
    61.     void Update () {
    62.         //re-select old objects to force repainting AnimationWindow
    63.         if(m_oldObjects != null) {
    64.             m_totalTime += (float)System.DateTime.Now.Subtract(m_lastFrameTime).TotalSeconds;
    65.             m_lastFrameTime = System.DateTime.Now;
    66.             if(m_totalTime >= 0.1f) {
    67.                 Selection.objects = m_oldObjects;
    68.                 m_oldObjects = null;
    69.             }
    70.         }
    71.     }
    72.  
    73.     void Fix() {
    74.         foreach(Animation ani in m_animations) {
    75.             AnimationClip[] clips = AnimationUtility.GetAnimationClips(ani);
    76.             foreach(AnimationClip clip in clips) {
    77.                 AnimationClipCurveData[] curves = AnimationUtility.GetAllCurves(clip);
    78.                 foreach (AnimationClipCurveData currentCurveData in curves) {
    79.                     string propName = currentCurveData.propertyName;
    80.                     if (propName == "m_LocalEulerAnglesHint.x") {
    81.                         AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.x", null);
    82.                         cIndex ++;
    83.                     } else if (propName == "m_LocalEulerAnglesHint.y") {
    84.                         AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.y", null);
    85.                         cIndex ++;
    86.                     } else if (propName == "m_LocalEulerAnglesHint.z") {
    87.                         AnimationUtility.SetEditorCurve(clip, currentCurveData.path, typeof(UnityEngine.Transform), "m_LocalEulerAnglesHint.z", null);
    88.                         cIndex ++;
    89.                     }
    90.                 }
    91.             }
    92.  
    93.             if (cIndex != 0) {
    94.                 Debug.Log(cIndex + "false items cleared!");
    95.             } else {
    96.                 Debug.Log("Nothing to clear!");
    97.             }
    98.  
    99.         }
    100.  
    101.         if(AnimationUtility.InAnimationMode()) {
    102.             AnimationUtility.StopAnimationMode();
    103.         } else {
    104.             //re-select objects to force repainting AnimationWindow
    105.             m_oldObjects = Selection.objects;
    106.             Selection.objects = new Object[0];
    107.             m_lastFrameTime = System.DateTime.Now;
    108.             m_totalTime = 0;
    109.         }
    110.     }
    111. }
     
  33. blueheartsprings

    blueheartsprings

    Joined:
    Oct 24, 2018
    Posts:
    1
    Is there a way to fix this without scripts yet? Using Unity 2020.3