Search Unity

UDK "AnimNotify" equivalent in Unity?

Discussion in 'Animation' started by Jason C., Sep 24, 2013.

  1. Jason C.

    Jason C.

    Joined:
    Sep 23, 2013
    Posts:
    2
    Hello all!
    We here at Juggernaut are furiously at work on a new 2D project utilizing the excellent Unity engine we all love. As the animator on this project, I've been trying to look into ways to streamline our process to lighten the load on our programmer, and simultaneously learning as I go. I have been perusing this forum and the Unity docs and haven't seen a related question, so thought I'd pose it to you guys.

    From what we have so far, animations for characters are driven by code, and we have been timing-out specific frame numbers for things like sound and visual effects. (i.e. Character footsteps fall on frames 10 and 20, play footstep audio on those frames). I was curious if Unity has an ability to have callouts during animations themselves, like the AnimNotify system in UDK; Where you can specify in-engine on a specific point in an animation to shoot-out a bit of script for code to latch onto and play an effect or trigger something.

    We saw the presentation on the new 2D animation features in Unity 4.3, and we're excited at the prospect of having that stuff built-in, but we also don't want to have to re-do a bunch of the work we have already done converting all of our skeletal rigs into the new 2D format.

    I appreciate any help or knowledge you guys can put forward on this. Thanks in advance! :D
     
  2. ChaseRLewis73003

    ChaseRLewis73003

    Joined:
    Apr 23, 2012
    Posts:
    85
    Depends on your system. I know 2DToolkit has a method (not as robust as I'd like to be honest) of having a callback function associated with a specific frame of animation. Since 2D animation isn't yet (but soon will be) supported by Unity except through customized codes any solution will be dependent on the framework the programmer created. The only other options is to create a SendMessage callback or something equivalent with a callback when an animation reaches a specific frame by monitoring it in code.

    You could try creating all your 2D animations with the 3D animation system, but that's masochistic. That's the reason a lot of Unity newbies think 2D isn't compatible with Unity, the base features are all 3D oriented. The new system I think is meant to alleviate the lack of native 2D support.

    A solution would be to have a separate component that monitors the animation of the sprite it is attached too and on certain frames have it send off a SendMessage("KeyFrameCallback",frameData);

    Then each component with a function has a method called "KeyFrameCallback" and can take the frameData will be called and processed. This allows each component to do something specific. So you can have a FootParticleEffect script that monitors for the 'run' animation to be playing and when KeyFrame = specific numbers it plays it.

    Hopefully the new unity system will support callbacks like the 3d animation system does.

    Example Code:
    Code (csharp):
    1.  
    2. [RequireComponent(typeof(SpriteAnimator))] //Made up class but you should get what it means
    3. public class KeyFrameMonitor : MonoBehaviour
    4. {
    5.    public SpriteAnimator spriteAnimator = null; //Best to use a property to verify this isn't null before use ... but trying to be simple
    6.    public const string OnFrameChange = "OnFrameChange";
    7.    public const string OnAnimationChange = "OnAnimationChange";
    8.    private string lastAnimation = "";
    9.    private int lastFrame = "";
    10. void Start()
    11. {
    12.    spriteAnimator = GetComponent<spriteAnimator>(); //Without a property verifying might get weird results in editor
    13. }  
    14. void Update()
    15. {
    16.     if(lastAnimation != spriteAnimator.currentAnimation.name) //Probably need a more specific way of identifying, but being simple
    17.    {
    18.      SendMessage(OnAnimationChange,spriteAnimator.currentAnimation);
    19.    }
    20.  
    21.     if(lastFrame != spriteAnimator.currentAnimation.currentFrame.number)
    22.     {
    23.          SendMessage(OnFrameChange,spriteAnimator.currentAnimation);
    24.     }
    25.    lastAnimation = spriteAnimator.currentAnimation.name;
    26.    lastFrame =  spriteAnimator.currentAnimation.currentFrame.number;
    27. }
    28. }
    29.  
    Code (csharp):
    1.  
    2.  
    3. [RequireComponent(typeof(KeyFrameMonitor))]
    4. public class OnKeyEvent : MonoBehaviour //Could make abstract...
    5. {
    6. public string animationName = "walking"; //Could make protected with this example ....
    7. public int frameNumber = 14;
    8. //Could do list instead ... your choice
    9.     public void OnFrameChange(SpriteAnimation animation)
    10.    {
    11.      if(animation.name == animationName  animation.currentFrame.number == frameNumber)
    12.      {
    13.          Callback(animation);
    14.      }
    15.     }
    16.    public virtual void Callback(SpriteAnimation animation)
    17.    {
    18.      //Empty derived class are what we really want
    19.    }
    20. }
    21.  
    Code (csharp):
    1.  
    2.  
    3. public class OnFootStep : OnKeyEvent
    4. {
    5.    //Can change OnKeyEvent values in inspector to "walk", "run", etc.
    6.    public virtual void Callback(SpriteAnimation animation)
    7.    {  
    8.       //Play effect you want for your footstep animation.
    9.    }
    10. }
    11.  
    12.  
    Their are more robust and better performance ways of doing this, probably would involve some custom inspector work though and this should give you an idea of how to create a system like that.
     
    Last edited: Sep 28, 2013