You could use Unity's StateMachineBehavior
component. I'll tell about it later.
However, it's actually might be an overkill feature that might bring up more complexity to the project than needed.
There's nothing wrong with your current approach as far as you keep things more or less readable and properly structured. The only other alternative (in addition to your current approach and StateMachineBehaviour
approach) would be a timer that would count down in every frame to check if the shoot cooldown is over, or reload time is over, and it's also a commonly used approach.
As for the isJumping
, isClimbing
, etc states when the gun shouldn't be able to shoot as well, these states should be managed in the character scripts while the gun's isShooting
, isReloading
, isJammed
states should be in the gun's scripts. That's how you keep things manageable. Player clicks Fire
button, you call Shoot()
method in the character script that checks the character's states such as isJumping
, etc, and then if everything is fine and the character is not busy you call the gun's Shoot()
method that checks if the gun is not already shooting or reloading currently.
Okay. The StateMachineBehaviour
. This is a thing that allows you to get certain predefined events from the animator states (nodes in the animator controller window) so you can do your stuff when the animator has entered an animation state, is currently performing some animation or the animation is over and the control is going to transition to some other state.
Here is the official manual: https://docs.unity3d.com/Manual/StateMachineBehaviours.html
The basic workflow is:
You open up the animator controller window of the gun's animator, select your 'Shoot' node, than in the inspector window you add a StateMachineBehavior
component to the node.
It should generate a script that has several methods like this:
//OnStateExit is called when a transition ends and the state machine finishes evaluating this state
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
}
(Not sure if this is exactly how it's done though, I didn't use the StateMachineBehaviour
for a long time).
That's what you're looking for - an event that fires when the 'Shoot' animation is over. There is also the OnStateEnter(...)
method available as well.
So, you could manage the gun's 'canShoot` boolean flag like this:
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
GunScript gun = animator.GetComponent<GunScript>();
gun.canShoot = false;
}
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
GunScript gun = animator.GetComponent<GunScript>();
gun.canShoot = true;
}
You would need to add similar components to other animator nodes like the gun's 'Reload' node, the player's 'Jump' node, etc, so whenever these animations are played the gun's canShoot
flag will be set to false
and get back to true
when the animation is over.