godotengine / godotengine/godot
AnimationTree.advance() on custom thread breaks update of the skeleton.
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
v4.3.stable.official [77dcf97d8]
### System information
Godot v4.3.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated GeForce 920M - Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz (4 Threads)
### Issue description
I've been unhappy with performance of skeletal animations so I moved everything to animation calculation on a **custom** thread inherited from Godot `Thread`. And is turns out that its not supported, and you'll say "of cause its not". But! You can make it work. You need some tricks. You need to call `advance()` on main thread once to create cache and then it can be updated. Also it need unique instances of `AnimationTreeNode`, sharing animation root is not an option here.
At first it gave me **4x** time performance boost as well if was not interfering with main thread ( _as oppose to running animation on **SubThread** which slows down main thread. And on **SubThread** it works fine, nothing breaks._ )
So while its running at first ok, after some time **skeleton** that is connected to `AnimationTree` stops updating positions. But transforms are still being calculated, animation still going. As you can see video below, I'm coping (_using simple_ `SkeletonModifier3D`) transforms from `AnimationTree` skeleton to **another skeleton** and its still being animated.
https://github.com/user-attachments/assets/7cc009f2-8165-4f69-b0e2-5bb213618e95
Anyway I've decided to report it as a bug. Since its possible and I'm not only one who will try it. And I feel like its totally possible.
One thing is calling `advance()` on thread will print an error to the console.
That because of `emit_signal(SNAME("mixer_applied"));` in the `AnimationMixer::_process_animation`. I have my edited version of engine where I just did this:
```
if(Thread::is_main_thread())
emit_signal(SNAME("mixer_applied"));
```
Behavior of bug is the same, regardless.
### Steps to reproduce
Run test project provided and wait for a while. Sometimes you need to wait a minute. Sometimes its 30 minutes.
### Minimal reproduction project (MRP)
[test_manual_advance.zip](https://github.com/user-attachments/files/18421243/test_manual_advance.zip)
Contributor guide
Research direction
Start by running the linked minimal reproduction project and waiting for the connected skeleton to stop updating. Then inspect AnimationTree.advance() and AnimationMixer::_process_animation, including the mixer_applied signal behavior described in the report. Done means identifying and fixing the custom-thread update failure without breaking the existing SubThread behavior, with a regression test if the relevant test location is established.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100