In my game, there are a bunch of bubble tanks roaming around and they all have bubbles that are animated with 2 18-frame spritesheets. One for the base of the bubble (so I can change the colour), and one for the white border of the bubble and the little dots in the center!
Bigger tanks will have more bubbles, and more bubbles mean more animator components running. I took a peek at the profiler and found that the animations’ total performance cost was quite significant and made some things like JobWaitForID and animation.start, animation.update etc etc quite high up on the performance cost list.
So that leads me to my question: Would it be worthwhile making a script on the root of the tank that collects all the bubbles that need to be animated and put them into an array and then have a coroutine that goes through all the bubbles and moves them to the next sprite in the spritesheet? Or should I just keep to having a separate animator component for each bubble?
This pattern is fairly common in Unity. I like to call it an Adaptor, and you might have more than one on a given object, such as one to manage colors, or one to manage animations, etc. It can interact with any local animators and then other parts of your code can just look for a color adaptor and work directly with that instead of caring about the details.
Generalizing and building more on this, here is a bit about using Interfaces in Unity3D: