So, the next story is somewhat long…
It all started when I wanted to improve my workflow, so I look up on the internet for some tips. At that moment, I was designing a weapon system for a 3D environment. I wanted a reusable, easy to implement solution, one that’d let me create as many weapons as I wanted with just little effort. I think I found a good solution for the weapon itself (shooting, reloading, etc), at least for me. But…there was still something I could not figure it out: the animations. I also wanted a simple method to implement the animations.
Later I found about Animator Override Controller. I knew they existed but I honestly never use it before.
So, from what I’ve read, they’re exactly the thing I was looking for. The docs says:
After watching some tutorials, it seemed that I only needed to create a base controller with some default states (in my case, Idle, Attack, Reload), and the Override Controller. The last one will replace the default animations inside the default states with the weapon ones:
After watching this tutorial, it was clear to me (I guess?) that the function of the Override Controller was to take and use the logic from the base controller to reproduce the required animation clips. At least in the example shown in the video, there wasn’t any code involve.
So, let’s take a look:
Sorry for the bad paint drawing lol, but that’s basically what I understood about the Override Controller. It is almost like using interfaces?..I mean, they aren’t, but I guess you get the idea.
So, I made my base controller, and the override one.
This is how the animator component looks on editor:
There’s also my weapon script. The script takes a reference of the animator (at the moment I manually set it, for testing purposes), and triggers the events according to the current state of the weapon. Since the ScorpionOverridesPlayer is taking the logic from the base controller, I don’t need to actually set up the base controller on the scene, isn’t it?..
Now, let’s see the Animator set up:
So…it kinda works. There are some weird things going on.
First, I’m not sure if I actually need to make a transition back from the Any State node, 'cause I honestly don’t remember doing it before, but for some reason whenever it gets to the DEFAULT_ATTACK or DEFAULT_RELOAD state, it never comes back to the DEFAULT_IDLE one. So…yeah.
There’s a trigger to perform the attack, and a boolean to perform the reload state (it makes sense, since the weapon is reloading for some amount of time, until it isn’t). Let’s ignore the DEFAULT_WALK state, since I haven’t set it up yet.
As I mentioned before, there are some issues. When I do the reload action (press the reload button), the animation starts repeating itself without finishing until it finishes. I know, that sounded weird, but let’s take a look to the code:
IEnumerator IReloadSequence()
{
_AnimatorController.SetBool(RELOAD_BOOL, true);
yield return new WaitForSeconds(_AnimatorController.ClipLength("Scorpion_Reload"));
_FX.AnimatorController.SetBool(RELOAD_BOOL, false);
audioSource.PlayOneShot(reload);
currentAmmo = currentAmmo + maxAmmoRound;
if (currentAmmo > maxAmmoRound)
{
currentAmmo = maxAmmoRound;
}
yield break;
}
I call this Coroutine though the method:
public void Reload() { StartCoroutine(IReloadSequence()); }
The extension method called ClipLength is one that I made to retrieve the current clip length (the animaton clip that’s playing at that moment). This is the code (btw based on this post ):
public static float ClipLength(this Animator animator, string animationName) {
var length = animator.runtimeAnimatorController.animationClips.First(clip => clip.name == animationName).length;
return length;
}
However, once I run the game, it seems that
yield return new WaitForSeconds(_AnimatorController.ClipLength("Scorpion_Reload"));
is completely ignoring the length of the animation clip, so it straight up jumps to
audioSource.PlayOneShot(reload);
and so on.
I ended up making that method because
_AnimatorController.GetCurrentAnimatorStateInfo(0).length;
was giving me a very similar result, but maybe worse, since the animation wasn’t even playing at all.
So, my first theory is that the GetCurrentAnimatorStateInfo is getting the info from the base controller. If that’s the case, the it would make total sense, since the DEFAULT_RELOAD state is technically empty.
And, if that’s the case, then how could I get the current animation clip lenght from the override controller? I guess that one way would be something very similar to the extension method ClipLenght, in which I specified using a string the name of the clip.
Speaking about that extension method, I didn’t want to use the string reference, since it completely ruins my generic implementation, but I couldn’t find another way of doing it.
So, yeah. I’m not sure about what to do now, since I’ve never been on this situation before.
Any idea that doesn’t involve just telling me “animator bad plz use my asset instead”? Because that’s an answer I’ve seen a lot…



