godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.64k stars 20.1k forks source link

Animations not looping on inherited scenes from a 3D gltf animated mesh #34394

Open NathanLovato opened 4 years ago

NathanLovato commented 4 years ago

Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Godot version:

Commit 3aa46a58cd3ae5f327929d127ac5fef0733176c9 Latest master from december 16, 2019

OS/device including version:

Linux Pop_OS! 19.10

Issue description:

In inherited scenes from animated 3D meshes, animations won't loop at runtime even though I set the animations to loop on the animation player. The animation does loop in the editor, the problem is only in-game.

Steps to reproduce:

  1. Import a .glb or .fbx rigged and animated mesh in Godot
  2. Create a new inherited scene from the imported mesh
  3. Select the animation player and set an animation to autoplay and loop
  4. Create a scene to see the character in the game
  5. Play the game

The animation doesn't loop. The looping setting is properly saved in the inherited scene: if you set the animated mesh scene to "Editable children" in the game scene, you'll see the looping option is still checked on the AnimationPlayer.

Note that if you clear the inheritance on the animated character, looping will then work as expected.

Minimal reproduction project:

Here is a working project with the issue above. The character is only in gltf2 but the issue is the same with fbx. I didn't include the fbx as the character's mesh normals won't import well at the moment.

animation-looping-bug.zip

fire commented 4 years ago

This bug is not related to https://github.com/godotengine/godot/issues/32678.

The animation needs to be saved as a separate .anim file so that the loop setting is saved.

fire commented 4 years ago

@NathanLovato Is using the cycle / loop hint flags enough for your use case?

NathanLovato commented 4 years ago

That is, naming the animations in Blender so that they loop properly in Godot? Sure, that would be fine by me.

fire commented 4 years ago

Please close the issue after testing with your model and animations.

NathanLovato commented 4 years ago

This bug report is about the loop animation checkbox not working in the Godot editor. While I'm fine using a workaround personally, shouldn't this button be at least disabled with inherited scenes from imported models? At the moment, you can still toggle it but it won't do anything.

fire commented 4 years ago

I wonder if we have a locked state for that button. We have on and off.

unfa commented 4 years ago

Doesn't this only break when using AnimationTree to drive the imported GLTF 2.0 scene's AnimationPlayer?

I have only had problems with animations not looping once I started using the AnimationTree. Before when I used the AnimationPlayer directly it was fine.

I was able to workaround this by adding a a piece of code that'll set the loop flags for specific animations on ready:

func _ready():

    var anim_player = $Mesh/AnimationPlayer
    var animations = ['Run', 'Idle', 'Idle2', 'Fly']

    for animation in animations:
        animation = anim_player.get_animation(animation)    
        animation.loop = true
NathanLovato commented 4 years ago

No, this happens with the raw inherited scene from the gltf file. See the steps and test project above.

fire commented 4 years ago

I can reproduce the issue.

fire commented 4 years ago

I can check if the animation resource is_local_to_scene(), but I have to go through everything. So I don't think it's the solution.

fire commented 4 years ago

Looks like this. https://github.com/fire/godot/tree/34394

https://github.com/fire/godot/commit/44c07c64bc28a8908a61ead67dccd5c098e010d0#diff-62dbccc2e9b8184a960eeca3afa931b1R1436-R1439

[Edited] This fix doesn't work.

KoBeWi commented 3 years ago

Still valid in 3.2.4 beta3

akien-mga commented 3 years ago

Confirmed in 3.2.4 RC 1 (following that same tutorial which prompted @NathanLovato to open this bug report :P).

To clarify on why this happens, the problem is that when you make an inherited scene from an imported animated mesh (glTF, FBX or Collada, should be the same for all), if the animations are embedded in that imported scene, they can't be modified, like other embedded resources of the imported scene.

The "Autoplay" property works as it's on the AnimationPlayer node, whose properties can be modified, but "Loop" is a property from the Animation resource, which seem to be read-only. I'm not sure if/how this could be fixed, though it's definitely unexpected. Note that there's a warning about it in the AnimationPlayer: Screenshot_20210201_213320

While that's not a fix, one workaround which is less problematic than losing the whole inheritance and converting the imported mesh to a standalone Godot scene (which creates big files - several MBs if using tscn) is to duplicate the animation that you want to modify (e.g. idle duplicated to idle-loop). That duplicated animation will then be local to the inherited scene and can be edited at will. Again, not a fix but documented this here for others who might run into the same issue.

Flavelius commented 3 years ago

I, too, was confused when the '-loop' suffix didn't actually made the animations loop. My understanding of imported files is that godot creates an internal intermediate object representing that file's content (the actual fbx file is not used in the runtime). Maybe i'm wrong with this assumption, but if not then i don't see a reason this internal representation can't be created in a way that respects import flags (still readonly if necessary, but with them already applied as default).

Nodragem commented 3 years ago

This bug report is about the loop animation checkbox not working in the Godot editor. While I'm fine using a workaround personally, shouldn't this button be at least disabled with inherited scenes from imported models? At the moment, you can still toggle it but it won't do anything.

I am playing with it at the moment and it does something: if you check the loop button, the animation is looping in the editor when you hit the play button of the animation tab. Hence, I believe that this checkbox is controlling the loop property of the AnimationPlayer, as opposed to overwriting the loop property of the animation itself? But for some reason, the behaviour is not the same when playing the game?

EDIT1: I was wrong, the checkbox is actually modifying the animation's property. It works in the editor because the property is modified in the RAM, then it stops to work in-game because the property cannot be overwritten on-disk (as it is part of a sub-node). You can find the original explanation here: https://github.com/godotengine/godot/issues/20467#issuecomment-409151082

@akien-mga as it is a question of sub-nodes that can't be overwritten, the fix is: 1) either to simply gray out the checkbox (the users can still use the -loop to mark an animation as looping) 2) or create an exception for the AnimationPlayer (because the looping properties do not actually exist in the imported files? so it would make sense that we can edit it?).

EDIT2: As suggested by reduz here (https://github.com/godotengine/godot/issues/20467#issuecomment-409161849), the default import could be changed to Animation > Storage > Files (.anim) This way the loop property checkbox in the AnimationPlayer works as expected by the user.

image

However, if we keep Built-in animations as an option, we would still need fix 1 or 2 (see EDIT1).

appastyle commented 2 years ago

confirmed this issue is still present in 3.4 stable, whats everyone been using for the best way to loop GTLF inherited animations?

EDIT: this workaround from a similar issue (https://github.com/godotengine/godot/issues/20467#issuecomment-625064956) worked for me:

The workaround is:

  1. create new animation player in the scene
  2. copy-paste animation from imported animation player to the new one
  3. in the animation tree use newly created animation player (not the one imported from glb)

you might have to clear inheritance from the scene to be able to delete the old animation player

dodgyville commented 2 years ago

EDIT: Updated and simplified after a great suggestion from KoBeWi below

My work around was to put this in a parent script:

func _ready():
    var  animation_player = get_node("Path/To/AnimationPlayer")
    animation_player.play("idle")
    animation_player.connect("animation_finished", animation_player, "play")

This is a "set and forget" that allows me to change the animation in the GLB outside of godot (using other tools) and automatically reimport it.

KoBeWi commented 2 years ago

Technically this should've worked too in a single line but I couldn't get the argument types to match up with the callback.

You don't need [anim_name], because animation_finished signal already passes it.

Calinou commented 2 years ago

Note that for AnimationTree users, this issue is also relevant: https://github.com/godotengine/godot/issues/40154

alfredbaudisch commented 2 years ago

The same issue is present in Godot 4 as well (alpha 12). I don't know if this is the right place to report?

elvisish commented 2 years ago

Still an issue in 3.5 apparently.

corjohnson commented 2 years ago

Just want to throw in my experience w/ Godot build from the main branch f2a616841

The imported file has an AnimationPlayer and I still use it in the instanced scene. But when looking at the loop settings for that clip, it's not set, and I cannot click the loop button because it's embedded in another scene.

I unchecked Optimizer for the import and nothing changed.


Quick update... after a few hours, I went back, opened the project and followed the steps of going to advanced import settings and saving the animation to a file, clicking re-import. And now the looping is working on the instanced scene. 🤷

StoreBoughtRocketGames commented 1 year ago

Out of curiosity, why was this issue closed? It's still present in Godot 4 Beta 4. Seems like a button to loop animations button should just work.

elvisish commented 1 year ago

You’re probably meant to add a loop tag to the name in the 3D editor, which is strange as other things can be imported and changed in Godot and it will just store the changes in the import meta data, specially material changes.

ginestopo commented 1 year ago

@StoreBoughtRocketGames an user with the same issue here. Godot won't let me loop an animation, as it is showing:

"Can't change loop mode on animation embedded in another scene."

My scene is literally not embedded in any other scene. I just opened the .glb file from the file explorer and created a new inherited scene as recommended.

Zireael07 commented 1 year ago

Inheritance is your issue here. The animation is embedded in the PARENT scene.

ginestopo commented 1 year ago

@Zireael07 so what is the best approach to treat it as an independent scene I can modify?

Edit: Because it won't let me change the mesh material neither.

Edit: I found the way! Right clicking the parent node and selecting this option will convert it into an independent one. Thanks for the hint @Zireael07 ! image

AlesLulak commented 1 year ago

Just adding my two cents for "Can't change loop mode on animation embedded in another scene" since I couldn't find "Clear Inheritance." in Godot 4 (however I am a newbie). When Godot asks to New Inherit or Open Anyway click on Open Anyway. Then you can right click on the tab and Save Scene as.... After saving it, looping works.

rmalizia44 commented 1 year ago

The best way I found was placing -loop after animation name in Blender, so when I export it to Godot, it will automatically loop and remove this suffix from animation name.

image

image

Tested in both 3.5.2 and 4.0.1 and this works, but 3.5.2 doesn't remove the -loop suffix from animation name.

thmsgntz commented 1 year ago

Hi there, I found an easy workaround to this (still up-to-date) issue. Godot version : v4.1.stable.official [970459615]

  1. Import normally your gltf scene in a 3D node, right click on it and hit "Editable children" button.

  2. Select the AnimationPlayer, In the animation panel, click on "Animation" to open "Manage Animations" : Capture d’écran 2023-07-23 à 15 44 30 3

  3. All animations should be grayed, but next to the "Global" root, click the disk icon and hit "Make it unique" :

Capture d’écran 2023-07-23 à 15 49 36

After that, it should work!

dark0ni commented 11 months ago

@thmsgntz big thx this was driving me nutz

lyuma commented 8 months ago

I think the intended workflow is to open the advanced importer dialog and set the Loop Mode on the imported animations. Can someone with this issue confirm if the Advanced Importer loop setting on the animation solves this. If so, this kind of works as intended in 4.x

I would like there to be a way to set a file-wide default setting for properties such as animation loop mode or physics, but that needs to be its own proposal.

corjohnson commented 6 months ago

I think the intended workflow is to open the advanced importer dialog and set the Loop Mode on the imported animations. Can someone with this issue confirm if the Advanced Importer loop setting on the animation solves this. If so, this kind of works as intended in 4.x

I would like there to be a way to set a file-wide default setting for properties such as animation loop mode or physics, but that needs to be its own proposal.

This is how I have done it recently with a GLB that I imported. Just set the loop mode for a few of the animations I needed it on (run/idle) in the advanced import settings & they loop as expected.

Running on 4.2.1 stable

mitchellkager commented 4 months ago

I think the intended workflow is to open the advanced importer dialog and set the Loop Mode on the imported animations

no amount of doing this then reimporting works for me, unless I save each animation to their own file and import those into my animation player instead of the original imports.