Best practice for checking if something ended C# ?

Hello,
I’m creating dynamic character, and often I need to check if animation, event, state etc has ended.
What is the best practice for this ?

I can think of three ways:

1 Using animation events (but this is extremely bad in some cases, events not being called, if interrupted - will never end etc)
2 Using timer (Kind of bad too, as different speeds of time, changed animations, frame rate… will make timer not accurate for event end)
3 For animation, checking if animation is no longer playing (Good, but what if fx., Boolean needs to be set for animation to end, so then animation will never finish its’ cycle)

I’m mostly interested perhaps in dealing with animations (how to see if animation has ended in most efficient way)

Any thoughts, opinions are very welcome

Thanks.

For animation events you can use a StateMachineBehavior. Put it onto animation clip in the controller, and you’ll receive callbacks. it is a bit tricky (because it is assigned to animation controller, meaning when you need to pass event to an object, you’ll need to extract actual object using "animator’ parameter…) , but it is pretty much the only reliable way to know animation is no longer playing specific clip.

Another idea is to combine events with state machine behaviors and assign timers to events in addition to that. So when you receive a notification from an event, you won’t do anything unless you’re also within specific clip (meaning you received specified notification on statemachinebehavior before that) AND you can assign timer/timeout on top of that - just in case.

I think this is one of the reasons why I canned using the Animator early on. Seemed like such a mess to work with. Especially for the 2D projects I was doing. I ended up just doing it the way I do in non-Unity work. Setting up animation tables in code and coding the animation. Then animation is easy to define, play and control including knowing exactly when complete.

I don’t see how someone could create an animation system focusing on stuff like state machines and not actually think to include support for this most fundamental thing such as knowing if an animation is still playing or has finished. It’s like so much focus was placed on the “gee whiz we’re advanced using visual state machines” part the other important bits were completely forgot. lol

I am not sure about 3D. I always figured for 3D animation I would need to build animation tables at a more detailed level of parent->part rotations and approach it in a similar way of coding the animation playing. And maybe that is the only way still to do it and have full control and access to such information as “are we done yet?”.

It’s all just rotations anyway (okay I suppose some translation maybe for secondary/supporting animations but I’d just have those as separate objects to begin with in that case).

1 Like

It is unfortunately very necessary for something like melee combat animation where you can move, block, kick, leap onto enemies, etc. At the same time you must ensure that your character won’t kill himself by drawing sword out because collider was still enabled.

So, statemachinebeahviors and animation events are absolutely necessary. How else are you going to, say throw a fireball? It detaches from characte’rs hand at a very specific frame, you’ll need to play a sound (possibly at different frame), etc.

Of course, unity state machines could use improvement, and could use equivalent of unreal’s montages. However in 3d animation is not something that you’ll be comfortable doing in code alone.

Here you go:
http://docs.unity3d.com/ScriptReference/Animator.GetCurrentAnimatorClipInfo.html
http://docs.unity3d.com/ScriptReference/Animator.GetNextAnimatorClipInfo.html

And in editor mode you can mess with things using AnimatorController.


Did you know that a single animator can have multiple state machines playing at once in parallel? Meaning, separate state machine controlling legs, and separate machine controlling torso, except that it only kicks in in very specific circumstances? And that you can have IK running in addition to that?

The solution to this and most other problems:

When in doubt, Debug.Log() like a mofo.

2 Likes

For Platformer PRO I have a concept of an AnimationBridge which acts as a bridge between game state and animation system (primary motivation is to transparently support different systems like Spine, Legacy, etc).

In the Mecanim bridges I check the current animation state and position each frame. There it is mainly so I know when to play the next queued animation if not using mecanim transitions, but you could do the same for raising an event when something ends.

Surprisingly it has minimal performance impact even when running across many characters, enemies and layers.

I’m not sure it qualifies as best practice, but writing your own layer gives you complete control, which I’ve found to be a good thing when working with Mecanim.

The basic gist is something like:

AnimatorStateInfo info = myAnimator.GetCurrentAnimatorStateInfo(layerOfInterest);
if (info.IsName(currentState.AsString()) && info.normalizedTime >= 1.0f ) {
  OnAnimationFinished(currentState, layerOfInterest);
}

(Note thats just an illustration of the concept)

1 Like

@neginfinity Yeah I think possibly the info is buried in the API / data structures some place. But I just didn’t like the workflow in general and am too lazy to get into all of that. Especially when I see no need to.

@JohnnyA That seems like a good way to go. Adds another layer but basically you can sort out of the stuff one time, build your own streamlined layer and use it from then on. Seems reasonable.

My own needs are basic and creating an animation table in code is very simple. If I had say a wizard of course I’d just need the meshes for head, arms, legs etc. I’d manually adjust these into poses for my key frames. A pose just defines the rotation targets required for each part for that specific pose / key frame. These would be coded into a table (so yeah I have some typing involved but I don’t mind it actually prefer it). Each animation sequence is just an array of these poses / key frames.

Then the actual animation code would simply rotate these parts over time to match the target angles in the next pose in the sequence. I always know exactly where everything is in the current animation sequence. If the wizard casts a fireball well I know they are performing a cast animation, have the poses / key frames involved and just spawn the fireball whenever I want to at what I think is the appropriate offset from the character’s main game object position.

I think maybe what makes this stuff seem complex to some folks is because they talk about IK and blends and stuff that I don’t care about. Although actually I don’t think it would be all that difficult to handle blends either. I’d just need to link key frames from different animation sequences to key frames in other animation sequences. But I see no need to. I don’t care if there is an abrupt transition between animations in a game. In fact to me I think that kind of thing is part of what makes a game a game and not a movie. :slight_smile:

Ha ha! This is very true. Although new tools have come out over time such as setting breakpoints and stepping through code, watching variable values and so forth for the most part I still rely on the same thing I was using 30 years ago. Back then it was Print and now in Unity it is Debug.Log.

I just remembered seeing your post when I was adding a door system to my current project and had added in a bunch of debug.log in a sort of test driven development way “Adding references of doors to list”, “No doors found in scene”, “Added x doors to list”, “Found door in front of player”, “Did not find a door in front of player”, “Door in front of player is locked”, “Player opened a door”, etc.

I never considered that someone may actually not use such a method to gain insight into what is going on. Gotta have info to work with.

I suppose it is possible there may be people who just try to figure it out without gathering any info. :hushed:

Yeah, to me it quickly became common sense if I was truely at wits end with a problem. It’s one of those old fashioned strategies that has a robustness to it in it’s simplicity.

I was working on an AI program for one of my games, and it was just broke all over, so I slapped like 12 Debug.Logs on that SOB. As I fixed problems and more of it was working, I’d comment them out until I was getting no logs, because then I knew it was working for sure.

All I know is, when you really can’t figure something out, Debug.Log got you.

That should be on the Unity API page for Debug.Log.

2 Likes