Search Unity

{SOLVED] Playing animations from a custom EditorWindow

Discussion in 'Scripting' started by thelackey3326, Aug 7, 2011.

  1. thelackey3326

    thelackey3326

    Joined:
    Sep 17, 2010
    Posts:
    34
    I needed to make a tool that, among other things, could play animations on a GameObject. Looked hard for an example, without much luck. What I found were clues that Animation.Sample() would be the solution. It wasn't. At least not for me. I couldn't get it to sample to any position in any animation on any GameObject. So I tried GameObject.SampleAnimation() instead, and it worked fine. Go figure.

    The hurdle for me was how to update the sample time. Turns out that EditorWindow has an Update() function that is called 100 times per second according to the Scripting Reference. So in the Update() function I just added 0.01f seconds to a time variable while playing. Seems to work.

    Thought I'd share my code just as an example. I've played several animations with it over the last half-hour or so. If anyone has tips for improvements, I'd love to hear them.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4.  
    5.  
    6. public class AnimUtility : EditorWindow
    7. {
    8.     private static AnimUtility s_window = null;
    9.  
    10.     private AnimationClip[] m_clips = null;
    11.     private Animation m_animation = null;
    12.  
    13.     private AnimationClip m_playingAnim = null;
    14.     private float m_time = 0.0f;
    15.  
    16.  
    17.     [MenuItem("Custom/Animation Utility")]
    18.     static void Init()
    19.     {
    20.         s_window = EditorWindow.GetWindow<AnimUtility>(true, "Anim Util", true);
    21.         s_window.Show();
    22.         s_window.Populate();
    23.     }
    24.  
    25.     void Populate()
    26.     {
    27.         m_animation = null;
    28.         m_clips = null;
    29.         GameObject activeObject = Selection.activeGameObject;
    30.         if (activeObject  activeObject.animation)
    31.         {
    32.             m_animation = activeObject.animation;
    33.             m_clips = AnimationUtility.GetAnimationClips(m_animation);
    34.         }
    35.     }
    36.  
    37.     void OnSelectionChange()
    38.     {
    39.         Populate();
    40.         Repaint();
    41.     }
    42.  
    43.     void OnDisable()
    44.     {
    45.         Populate();
    46.     }
    47.  
    48.     void OnGUI()
    49.     {
    50.         if (m_clips != null)
    51.         {
    52.             GUILayout.BeginVertical();
    53.             {
    54.                 foreach (AnimationClip anim in m_clips)
    55.                 {
    56.                     if (GUILayout.Button("Play " + anim.name, GUILayout.ExpandWidth(false)))
    57.                     {
    58.                         m_animation[anim.name].normalizedTime = 0;
    59.  
    60.                         m_playingAnim = anim;
    61.                         m_time = 0.0f;
    62.  
    63.                         Debug.Log("Playing " + anim.name);
    64.                     }
    65.                 }
    66.             }
    67.             GUILayout.EndVertical();
    68.         }
    69.     }
    70.  
    71.     void Update()
    72.     {
    73.         if (m_playingAnim)
    74.         {
    75.             Selection.activeGameObject.SampleAnimation(m_playingAnim, m_time);
    76.             m_time += 0.01f;    //Update() is reportedly called 100 times per second
    77.  
    78.             if (m_time > m_playingAnim.length)
    79.             {
    80.                 m_playingAnim = null;
    81.  
    82.                 Debug.Log("Done playing " + m_playingAnim.name);
    83.             }
    84.         }
    85.     }
    86. }
    87.  
     
  2. MattMaker

    MattMaker

    Joined:
    Oct 4, 2009
    Posts:
    6
    Hey, thanks! This was exactly what I needed today. I also needed to run sequences of animations, so I hacked it up some to do that:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections.Generic;
    5.  
    6. public class AnimUtility2 : EditorWindow
    7. {
    8.     private static AnimUtility2 s_window = null;
    9.  
    10.     private AnimationClip[] m_clips = null;
    11.     private Animation m_animation = null;
    12.  
    13.     private float m_time = 0.0f;
    14.    
    15.     private bool m_isPlaying = false;
    16.     private bool m_isLooping = false;
    17.     private List<AnimationClip> m_playingAnimSequence = new List<AnimationClip>();
    18.     private Dictionary<AnimationClip, bool> m_useAnim = new Dictionary<AnimationClip, bool>();
    19.  
    20.    
    21.     [MenuItem("Custom/Animation Utility2")]
    22.     static void Init()
    23.     {
    24.         s_window = EditorWindow.GetWindow<AnimUtility2>(true, "Anim Util", true);
    25.         s_window.Show();
    26.         s_window.Populate();
    27.     }
    28.  
    29.     void Populate()
    30.     {
    31.         m_time = 0.0f;
    32.         m_animation = null;
    33.         m_clips = null;
    34.        
    35.         if (m_playingAnimSequence != null  m_playingAnimSequence.Count > 0) {
    36.             //for (int i=0; i<m_playingAnimSequence.Count;i++)
    37.             m_playingAnimSequence.RemoveRange(0, m_playingAnimSequence.Count - 1);
    38.         }
    39.        
    40.         m_playingAnimSequence = new List<AnimationClip>();
    41.         m_useAnim = new Dictionary<AnimationClip, bool>(); //TODO Remove old ones?
    42.        
    43.         GameObject activeObject = Selection.activeGameObject;
    44.         if (activeObject  activeObject.animation)
    45.         {
    46.             m_animation = activeObject.animation;
    47.             m_clips = AnimationUtility.GetAnimationClips(m_animation);
    48.         }
    49.        
    50.         if (m_clips != null  m_clips.Length > 0) {
    51.             foreach (AnimationClip clip in m_clips) {
    52.                 if (!m_useAnim.ContainsKey(clip))
    53.                     m_useAnim.Add(clip, false);
    54.             }
    55.         }
    56.     }
    57.  
    58.     void OnSelectionChange()
    59.     {
    60.         Populate();
    61.         Repaint();
    62.     }
    63.  
    64.     void OnEnable()
    65.     {
    66.         Populate();
    67.     }
    68.  
    69.     void OnGUI()
    70.     {
    71.         if (m_clips != null)
    72.         {
    73.             GUILayout.BeginVertical();
    74.             {
    75.                 foreach (AnimationClip anim in m_clips)
    76.                 {
    77.                     bool prev = m_useAnim[anim];
    78.                     m_useAnim[anim] = GUILayout.Toggle(m_useAnim[anim], anim.name + " " + anim.length + "s");
    79.                     if (m_useAnim[anim] != prev) {
    80.                         if (m_useAnim[anim]) {
    81.                             m_playingAnimSequence.Add(anim);
    82.                         } else {
    83.                             m_playingAnimSequence.Remove(anim);
    84.                         }
    85.                     }
    86.                 }
    87.                 GUILayout.BeginHorizontal();
    88.                 m_isLooping =  GUILayout.Toggle(m_isLooping, "Loop ", GUILayout.ExpandWidth(true));
    89.                 m_isPlaying = GUILayout.Toggle(m_isPlaying, "Play ", GUILayout.ExpandWidth(true));
    90.                 GUILayout.EndHorizontal();
    91.             }
    92.             GUILayout.EndVertical();
    93.         }
    94.     }
    95.  
    96.     void Update()
    97.     {
    98.         if (!m_isPlaying) return;
    99.         if (m_playingAnimSequence.Count > 0) {
    100.             //Debug.Log("playing Sequence of " + m_playingAnimSequence.Count + " clips");
    101.            
    102.             Selection.activeGameObject.SampleAnimation(m_playingAnimSequence[0], m_time);
    103.             m_time += 0.01f;    //Update() is reportedly called 100 times per second
    104.  
    105.             if (m_time > m_playingAnimSequence[0].length)
    106.             {
    107.                 Debug.Log("Done playing " + m_playingAnimSequence[0].name);
    108.                 m_time = 0.0f;
    109.                 if (m_isLooping) {
    110.                     //remove it and add it back to the end
    111.                     AnimationClip ac = m_playingAnimSequence[0];
    112.                     m_playingAnimSequence.Remove(m_playingAnimSequence[0]);
    113.                     m_playingAnimSequence.Add(ac);
    114.                 } else {
    115.                     //uncheck it and then remove it
    116.                     m_useAnim[m_playingAnimSequence[0]] = false;
    117.                     m_playingAnimSequence.Remove(m_playingAnimSequence[0]);
    118.                     Repaint();
    119.                 }
    120.             }
    121.         }
    122.     }
    123. }
     
  3. 6sizerg

    6sizerg

    Joined:
    Jan 23, 2014
    Posts:
    1
    Some Lines has grammatical errors.
    (Ex,#30 Line first script ....... if(activeObject activeObject.animation)....???)
    You can figure out them with C+V on your compiler editor.

    But this scripts very helpful for me!
    Using Update() for time const is very brilliant!
    I was confusing with .timeSinceStartup.
    Thank you

    ps. Sorry for my poor English. It's not my native language.
     
    Last edited: Dec 17, 2015
  4. startassets

    startassets

    Joined:
    Feb 13, 2017
    Posts:
    11
  5. sisi0616

    sisi0616

    Joined:
    Jan 17, 2019
    Posts:
    3
    What should an animator component do if the component used in gamebeobject is not an animation component?
    help me...