Okay, so I just spent the whole past day refactoring everything I had so that each character is its own scene. I then had a whole huge post written out with questions and pictures, but I can’t post multiple pictures as a new user, and then I had some more time to think for a night, and figured the solution had basically been reached. So here is what it comes down to.
There seems to be two solutions.
First, there is what @normalized said. You have one base scene. Now you want to use animations as resources, data for each character. The editor doesn’t have a way to automatically change the node paths of your saved animations if you change the node paths in your base scene, so you need to write a tool to do it for you. Upon thinking of it, this is probably simple if you know what you’re doing. There is also Issue 1 of this post: the animation names need to match the state names. You can also write a tool for this.
In my mind, the tools would do something like this: for the state renamer tool, you would make a tool that allows you to input the new name for a state. It could then loop through your animations and rename them accordingly. I don’t know how you would give it the animations; I’m not experienced with creating tools, but I think this would be the basic idea. Maybe you could make an even better tool that could ensure the names of your animations match the state names as you create them, but that might not be necessary.
For the node path changer tool, well, same concept. It has access to all of your animations and access to the base scene. I believe the engine already emits a signal when nodes are moved around or reparented (have not checked), but if it does, you could connect to that. When the node paths are changed, loop through your animations, check to see if the old node paths of any of them were the ones that changed, then update them accordingly. The editor basically already does this if your animations are in the editor, just not if they’re saved as resources, which is why you would need a tool instead.
Then, there is the solution by @zigg3c, which I think I have come to terms with. If all of your characters have different animations (which means, even if it’s just the number of frames that’s different), then that is reason enough to make a new scene for each character.
The one-scene-per-character approach, of course, works. It solves Issue 2 on its own, since the animations are just kept in the editor and update on their own. The way I solved my Issue 1 this way was like this:
My state machine became a base, abstract class for different types of state machines. So I extend it and create a new type of state machine for each type of character/enemy. This way, the state machine knows exactly what states it has in it:
class_name IdlerMachine
extends StateMachine
@export var animation_player: AnimationPlayer
#These are states, which are just RefCounteds
var idle := Idle.new()
var fall := Fall.new()
func init() -> void:
state_order = [
fall,
idle
]
Now, my problem is that when I create a new animation for the scene, how do I remember what the animations need to be called, and how do I protect them from breaking if I ever change the string used for each animation in the states?
The answer: the states don’t call a magic string, and you export the names of the animations in the state machine, so they can be filled out per scene.
The states do something like this, now:
class_name Idle
extends State
var idle_animation: StringName
...
func some_func():
animation_player.play(idle_animation)
And the IdlerMachine gets this simple code:
@export var idle_animation: StringName
...
func _ready():
idle.idle_animation = idle_animation
So when you’re making animations for your specific scene, you call your animations whatever you want, and then just easily type them into the editor. The state machine passes on the names. Now you only need to know what’s in your scene, and you don’t have to worry about changing the names of the states later; just update what the variables are called if you want, and nothing breaks.
I think I have decided, after much internal conflict, to just do one scene per character now. The drawback, of course, is that if you want to change something about all of them later, it will be harder. But it seems like most changes you would want to make are not substantial enough that you couldn’t fix them by just adding some code to one of the components. Doing a scene per character is also more flexible per character, even if you don’t PLAN on making them different for the time being. Does this mean you will have to rebuild the same scene over and over a lot? Yes, but it’s just clicking and dragging, not literally writing the same code over and over.
I would say that for my game, this is fine.