Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
8
Question by castor · Jul 17, 2014 at 05:49 PM · triggermecanimstate

Mecanim - Trigger event at end of animation state

Not sure if I'm doing something wrong here or totally lost in the way the system works. Here is the situation:

I have an actor on the floor and handcuffed, his animation state is called handcuffedIdleState. When the other actor beats him up he will go to a new state called handcuffedKickedInHeadState by using a trigger:

 animController.anim.SetTrigger("isKickedInHead");

Once that animation has played, he returns to the original state handcuffedIdleState. I need to know when the actor has finished the handcuffedKickedInHeadState so I can trigger his reaction. To do that I run the following function on Update():

 if(animController.currentBaseState.nameHash == animController.handcuffedIdleState){
     //React to kick
 }

Now my problem is, since he STARTED on handcuffedIdleState, this will immediately be true, even before the animation started. So I decided to add a couple more lines.

 //Make sure the 'isKickedInHead' trigger is no longer true AND
 //That the animation is not in transition
 if(
     !animController.anim.GetBool("isKickedInHead") &&
     !animController.anim.IsInTransition(0) &&
     animController.currentBaseState.nameHash == animController.handcuffedIdleState
 ){
     //React to kick
 }

But still, this is immediately true even before the handcuffedKickedInHeadState started. I can't figure out a sure way of knowing when the new animation has finished and I've arrived at the Idle State...

UPDATE - Another way to look at the problem

So the main issue here is that I'm returning to the animation I started. I'm going from A(1) -> B -> A(2) and I'm trying to figure out when I'm back at A.

B can be anything so its not something I can rely on. B can be a different state so putting events on B or even trying to track it is not an option.

This is what I usually do:

 if(
     !animController.anim.IsInTransition(0) &&
     animController.currentBaseState.nameHash == animController.stateA
 ){

The problem is, once the transition is over, for ONE frame, before B becomes the currentBaseState, A(1) is the currentBaseState. This makes it impossible to use A for the comparison...

In case I'm not being clear, here is a little graphic I did for myself to understand the problem (the orange box is the problematic frame):

alt text

states.jpg (171.0 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
13
Best Answer

Answer by castor · Jul 18, 2014 at 06:03 PM

I asked the question on the forums and TonyLi gave me the solution. Posting here for future reference.

The way to solve my issue is by knowing what is the next state that is getting played during the transition using GetNextAnimatorStateInfo .

So by doing something like this:

  if(
         anim.IsInTransition(0) &&
         anim.GetNextAnimatorStateInfo(0).nameHash == animController.stateA
     ){
         //Do reaction
     }

This makes sure that I'm only triggering the reaction when I'm in the transition OUT of stateB and towards A (since i would never be transitioning from A to A). So this works cleanly and super nice no matter what the initial state is!

For more details on the question, here is the forum link http://forum.unity3d.com/threads/mecanim-going-from-statea-stateb-statea-knowing-when-second-statea-has-started.257635/

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
4

Answer by Xtro · Jul 17, 2014 at 05:59 PM

You can add a event at the end of the mecanim animation so that Unity will call your event method when it hits the event trigger on the animation automatically.

For more info, please see the answer under this question : http://answers.unity3d.com/questions/615041/mecanim-animation-events-1.html

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image castor · Jul 17, 2014 at 06:02 PM 0
Share

But then what is the point of using the state machine? The kickInHead can trigger different animations depending on the situation. It doesn't make sense to me that I need to create events at the end of every possible state to know that I left it. Isn't that the purpose of using $$anonymous$$ecanim? (Also I was the one who replied to that answer :P)

avatar image infinitypbr · Jul 17, 2014 at 06:26 PM 0
Share

I think he means put the trigger @ the end of the "is$$anonymous$$ickedInHead" animation.

If there shouldn't always be a reaction at the end of that, just add a 2nd boolean or counter in your scripting so that although the function is called, if no reaction is needed none is started.

avatar image castor · Jul 18, 2014 at 03:59 AM 0
Share

Thats what I understood. But the "is$$anonymous$$ickedInHead" is just a trigger, it calls different "kicked in head" states with different animations depending on the situation. I also don't like the idea of having events on the animations (unless its for audio of pfx) since sometimes the animation might be used in other states and its not something you can clearly see in your script or the state machine, you have to go and dig on your animation list.

avatar image Tom-Atom · Jul 22, 2015 at 07:35 PM 0
Share

@Xtro Unfortunately Animation events are very unreliable. Here are problems I encountered: http://forum.unity3d.com/threads/animation-events-not-triggered.341916/

avatar image castor · Jul 22, 2015 at 08:24 PM 0
Share

Not only animation events. I've realized that the solution I've presented doesn't work well when time is speed up, where this unique frame moment is easily skipped.

avatar image Deepscorn castor · Sep 14, 2015 at 06:50 AM 1
Share

Yes, as stated in http://answers.unity3d.com/questions/806949/animation-events-not-firing.html the frame can be skipped and event not fired. When you need event at start or end of animation you can write State$$anonymous$$achineBehavior script and add it on animator state (not animation!)

Show more comments
avatar image
0

Answer by DarkGate · Jan 31, 2016 at 02:28 PM

This is a bit late, but you can use a coroutine to check for the end state. In your case, it would be:

 IEnumerator onComplete() {
 
     while (animator.GetBool("kickedInHead")) {
         Debug.Log("Animation in progress!");
         yield return null;
     }
 
     // this will get here when kickedInHead is false
     Debug.Log("Animation complete!");
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Alverik · Apr 30, 2016 at 11:35 AM

ummm... still using mecanim animation events, couldn't you just have used two copies of the same idle? Then used events in the first, transitioned to the hit, then transitioned to the other copy of the idle (the one without the events)...

Although, I guess, project space wise, it may not have been the most efficient method (if you have a small target size)...

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Mecanim - Trigger event Invokation 0 Answers

Trigger the same state again? 1 Answer

on trigger enter - play mecanim animation 0 Answers

Synchronize two animator states to have the same normalized time - Mecanim 0 Answers

Wait mecanim animation to finish before doing more instructions 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges