'AnimationPlayer seek() using threading
I have a script attached to an AnimationPlayer node and it does some long calculations,
so in order to avoid the game engine from hanging while those calculations take place
I created a separate thread for that function,
but the seek() function doesn't update the animation despite adding update=true
I've narrowed it down to this simple example:
extends AnimationPlayer
tool
export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
var thread;
func sep():
self.seek(aniTimer,true);
# calculations #
func aniTimer_Changed(new_val):
aniTimer=new_val;
thread = Thread.new();
thread.start(self, "sep");
here's how the tree looks like:
so how to I get the seek() to work or is there any workaround with what I'm trying to achieve?
Edit:
I tried applied the solution @Theraot gave & modified it to loop through all the animations
like this:
func sep(thread:Thread):
var AnimationList=self.get_animation_list();
for animation_name in AnimationList:
self.current_animation=animation_name;
var ongoing_animation=self.get_animation(animation_name);
for track_indx in ongoing_animation.get_track_count():
for key_indx in ongoing_animation.track_get_key_count(track_indx):
var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
self.seek(key_time,true);
Translate=false;
property_list_changed_notify();
thread.call_deferred("wait_to_finish")
func Translate_Changed(new_val):
if _thread == null or _thread.is_active():
_thread = Thread.new();
_thread.start(self, "sep", _thread);
But when I run this for a big animation it gets stuck in between & the entire godot game engine hangs
I'm guessing it's a memory leak?
what am I trying to achieve?
I've actually created custom properties on a node and added those custom properties as keys in an AnimationPlayer
but these custom properties all effect position, rotation & other inbuilt properties.
so I thought by seek() I could see the end result of all them combined and then key the position, rotation & other inbuilt properties to another AnimationPlayer
Solution 1:[1]
After testing, it appears to me that it works with a couple caveats:
- You need to take proper care of the thread. Which I explain below.
- The change will not be reflected in the Animation panel. However you should be able to see the animation take effect on the nodes.
Once done properly it works on Godot 3.2 or newer. However, starting with Godot 3.4 I could be more sloppy with how I handle the thread and it would still work.
First of all, you need to call wait_to_finish when the thread ends. Not doing it will prevent proper cleanup. If you don't have code waiting for the thread to finish, you can add this at the end of the thread code:
thread.call_deferred("wait_to_finish")
Using call_deferred (or set_deferred or emit_signal) allows the thread to issue operations on the main thread.
By the way, you can reuse the thread by calling start on it again after it finished. So you don't need to create a new Thread each time. So you can do this:
if thread == null:
thread = Thread.new()
But! The thread will be running for the long computations, and you cannot call start on it while it is running. A simple solution is to start another one:
if thread == null or thread.is_active():
thread = Thread.new()
I don't know if there are race conditions to be aware of. Take into consideration the possibility of two threads running at the same time.
But! that means that when the thread calls thread.call_deferred("wait_to_finish") that would not be the correct one. So we are going to pass the thread as parameter to the thread.
This is how my code looks like:
tool
extends AnimationPlayer
export(float,0,1,0.1) var aniTimer = 0.0 setget aniTimer_Changed
var _thread:Thread
func sep(thread:Thread):
seek(aniTimer, true)
# calculations #
thread.call_deferred("wait_to_finish")
func aniTimer_Changed(new_val):
aniTimer=new_val
if _thread == null or _thread.is_active():
_thread = Thread.new()
# warning-ignore:return_value_discarded
_thread.start(self, "sep", _thread)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |


