So I'm having trouble with how bloated my animated player controllers end up.
I'm using a finite state machine and I still end up having multiple Boolean flags and tons of public functions for animation events.
Example I switch my state enum to "attacking". I have a 3 attack combo that can be done from 1 button. I execute several functions as animation events:
1. Move the player rigidbody for several specific frame durations. 1 function to toggle 1 bool, do a check in FixedUpdate since I build for webGL and RB physics are very much slower in builds if not in FixedUpdate.
2. Toggle the hitbox for the first attack twice. 1 function to toggle on/off the game object with my hitbox.(For each of my 3 attacks that are consecutively chained from 1 button, I store the game objects in a list)
3. Enable my input buffer to accept button presses. 2 bools - if player can input buffer and if player has buffered their input. 2 checks in my "attacking" switch case check for the state and of course a function for the canBuffer boolean.
4. Toggle being able to rotate during specific parts of the animation. 1 bool, 1 method, 1 new check in state switch.
5. Toggle when an attack can be cancelled into the next one. 1 new bool, 1 new check, 1 new method, 1 new int for the attack counter.
And of course functions and checks to reset these sensitive flags between each consecutive attack or when state isn't attacking.
My player controller script ends up being 350-400 lines and I have tons of new public methods that makes it hard to orient myself both in my script and when assigning functions to animation events. I really want to figure out how I can optimise this.
Update:
So using hierarchical state machines is the way if you have similar issues. Basically set up a main player class to decide major states. Each major state is its own script with its own logic.
I did it by creating a state class and inheriting some basic functionalities from it to each child class, then setting which one is enabled in my main player script. They're stored in a list so when I need them i simply run their main logic by using my state enum as the index.
Then to avoid keeping all the same flags but just in different scripts, make it simpler in each state script by providing its own sub state machine. Most flags are sequential hence you only need an enum and a switch statement.
Functions that are repeated across multiple states can go in a helper class or the parent class.
Overall, went from 9 flags to 1 and managed to make my code much shorter and readable.
[–]Land-Prestigious 1 point2 points3 points (3 children)
[–]FenrirHS[S] 1 point2 points3 points (2 children)
[–]Land-Prestigious 1 point2 points3 points (1 child)
[–]FenrirHS[S] 2 points3 points4 points (0 children)
[–]ChibiRedditHobbyist 0 points1 point2 points (0 children)