OnItemUseComplete randomly not called

revenz

New member
Hi,

I'm trying to add some melee attack animations, which have the animation events
  • OnAnimatorItemUse
  • OnAnimatorItemUseComplete
These work for a while, and the "ItemUseComplete" is called in MeleeWeapon. But then suddenly it just stops working. The animation has completed, the animator is now stuck on the last attack animation (the Animator shows a full blue bar under the attack animation) and nothing else can happen. It cant leave this animation as "Slot0ItemStateIndex" is still on 2.
Screenshot_2.png
I know this is an issue on my side, I'm just hoping someone could help me out as to where to look to find where it might be?
Screenshot_1.pngScreenshot_3.png
 
Here are a couple more screenshots. I've only got 2 animations at the moment (to narrow down the error)

Screenshot_4.png

Screenshot_5.png

Screenshot_6.png
 
Further digging it appears this is false
if (usableItem == null || !m_WaitForUseCompleteEvent[slotID])
in the method Use.UseCompleteItem, m_WaitForUseCompleteEvent[slotID] is false which stops the ability from continuing/ending.

The animation event is correctly firing off in AnimatorMonitor.ExecuteEvent. Just the Use ability is getting stuck.....
 
Revenz,

replying to your post here, Try turning off "Allow attack Combos" within the Melee weapon script then spam the "Fire1" button excessively if no locks occur, turn it back on spam "Fire1" if locks occur - start changing the "Reset Delay" to see if this is interfering with the combo actions. I am currently not using the "Reset Delay" at all for my Melee weapons. Try this on 0. if still find animation locks - you will need to work on the Mecanim transitions. check out Opsive Demo scene mecanim transitions for reference.

Quote from Justin @ Opsive "If your animator is getting stuck you should first ensure all of the parameters are what you'd expect them to be. If they aren't then it's likely an event issue. If they are then it's likely a missing transition between the current state and the state that you'd like to transition to."

Allow Attack Combos.png

ResetDelay.png

Hope you find the fix.

Cheers,
 
thanks, I think I got it now. I had to keep reset delay set, 0 wouldn't work. But I increased "Use Rate" to 0.6 which seems to have solved it. Not a huge fan of this though as its a hardcoded time variable instead of an animation event. Maybe I should subclass the "Melee Weapon" script and only allow one itemstateindex increase at a time, but surely the melee weapon script will be doing this already....
 
ehh, I'm sure there is a bug here. The problem is a Slot0ItemSubStateIndex can transition multiple indexes before the current one completes.

So it doesn't always go in the correct order of attack 2, 3, 4, 5, 2 etc.

You can kinda fix this by adjusting that "Use Rate". But that's also not perfect as it is a globe time to wait and not per attack. And each attack might have different durations (quick jab vs big power swing for example). And that also can make you skip from 2 to 4 etc. It does prevent skip 2 all the way back to 2 again, but still.

Surely the "Sequence" selector should only allow you to increase the SubstateUseIndex by 1 until that one has completed, not whenever you push attack.

I'm trying to fix this in a subclass of MeleeWeapon, which isn't going so well..

C#:
    public class RMeleeWeapon : MeleeWeapon
    {
        private int CurrentSubstateIndex = -1;
        private int FirstSubstateIndex = 2; // figure this out later
        private int LastSubstateIndex = 5; // figure this out later


        public override bool CanUseItem(ItemAbility itemAbility, UseAbilityState abilityState)
        {
            if (abilityState == UseAbilityState.Start)
            {
                int nextIndex = m_UseAnimatorAudioStateSet.GetItemSubstateIndex();
                if (CurrentSubstateIndex != -1 && nextIndex == CurrentSubstateIndex)
                    return false;

                if (CurrentSubstateIndex == LastSubstateIndex)
                {
                    if (nextIndex != FirstSubstateIndex)
                        return false;
                }
                else if (CurrentSubstateIndex != -1 && nextIndex > CurrentSubstateIndex + 1)
                    return false; // too fast, must wait
            }


            return base.CanUseItem(itemAbility, abilityState);
        }

        public override void StartItemUse(ItemAbility itemAbility)
        {
            CurrentSubstateIndex = m_UseAnimatorAudioStateSet.GetItemSubstateIndex();
            base.StartItemUse(itemAbility);
        }

        public override void ItemUseComplete()
        {
            CurrentSubstateIndex = -1;
            base.ItemUseComplete();
        }
    }

This is what I have so far, I think I'm going down the wrong path though. Maybe this fix should go inside the Use ability instead...
 
Can you tell me how to reproduce the index increasing too fast within the demo scene? I can take a closer look at it.
 
Fairly easy to reproduce. I repo'd this in a new project, with just Opsive 3rd person controller imported.
  1. Third Person Controller Version 2.3.3
  2. Unity version: 2020.3.12f1 Personal running on Windows 10.

In the "Full Body Layer" I removed the "Sword" substate and created this modified version
1624957660913.png

It just reduces it down a bit, and only lets you the attacks in order, 2,3,4,5. I copied the "Any State", "Exit" conditions from the original sword attack, and same with the conditions from Attack 1 to 2, just for the 3rd, 4th I increased the Slot0ItemSubstateIndex to 4 and 5

On the "Nolan" character "Items" "Sword". Add two more "Animator Audio States" 4 and 5:

1624957763588.png
Nothing fancy here.

Hit run, open the Animator, turn off "Auto Live Link" go into the new "Sword" substate, watch the "Slot0ItemSubstateIndex" value.

Spam the attack button. I found this is easiest with mouse left click over a controller. You should see it jump up 2 substate index values before the attack animation finishes, causing it to get stuck, as there is no transition from substateindex 2 to 4 etc.
 
Last edited:
Thanks, I just tested it and I think that things are working as intended.

The next index will be called anytime UsableItem.StartItemUse is called. StartItemUse is limited by the Use Rate so that's why you are seeing the current behavior. The melee weapon doesn't not require the complete event to first occur so it can queue up the next attack while the current attack is active.

If different animations should have different use lengths you can use the AnimatorAudioStateSet to enable/disable a state which changes the Use Rate for each animation.
 
thanks. Turns out the best "fix" for this is to actually remove the "Slot0ItemSubstateIndex" from the transitions to each combo attack.

1625081400004.png

So each connection between Attack01 -> Attack02 -> Attack03 -> Attack04 -> Attack01 just has these conditions
1625081443235.png
Where "Moving" is optional, and I may remove it... I haven't done the upper body layer yet, this is all in full body layer to get working first.

And the "Any State" to each attack has these
1625081472103.png
Where The Slot0ItemSubstateIndex corresponds to each attack.

Obviously, this solution would not work if the Selector was "Random". But if the "Selector" was "Random", then you would have connections to every possible attack including to itself so you shouldn't have the problem I've been having.

This seems to solve my issue, in case anyone else stumbles upon this in the future.

I was worried I might be able to spam the attack button and there would be heaps of attacks running after I stopped pushing attack. But by using the States as you mentioned, I can use the default Use Rate for the common length attacks to something around 0.2 then the longer attacks to 0.5 and this seems to stop queuing up lots of attacks.


Thanks for all the help, I really appreciate it.
 
Last edited:
Top