V-Sekai / godot-vrm

Importer/Exporter for VRM avatars and MToon shader. Available for Godot 4.1+ and 3.2+ in the Asset Library.
https://godotengine.org/asset-library/asset/2031
Other
287 stars 24 forks source link

Errors thrown when loading models in background thread #99

Open robertdhernandez opened 7 months ago

robertdhernandez commented 7 months ago

To avoid stalling the main thread, I am loading VRM models at run-time in a background thread. The official Godot documentation specifies in the thread-safe API:

Interacting with the active scene tree is NOT thread-safe. However, creating scene chunks (nodes in tree arrangement) outside the active tree is fine. This way, parts of a scene can be built or instantiated in a thread, then added in the main thread.

I have gotten background loading to work, however some models throw an error when loading:

E 0:00:02:0128   vrm_utils.gd:77 @ rotate_scene_180_inner(): This function in this node (AliciaSolid_vrm-0_51) can only be accessed from either the main thread or a thread group. Use call_deferred() instead.
  <C++ Error>    Condition "!is_readable_from_caller_thread()" is true. Returning: (Transform3D())
  <C++ Source>   scene/3d/node_3d.cpp:333 @ get_transform()
  <Stack Trace>  vrm_utils.gd:77 @ rotate_scene_180_inner()
                 vrm_utils.gd:89 @ rotate_scene_180()
                 vrm_extension.gd:966 @ _import_post()
                 vrm_model_loader.gd:94 @ _load_model()
                 vrm_model_loader.gd:75 @ _load_models_threaded()
...
E 0:00:02:0244   vrm_utils.gd:106 @ apply_node_transforms(): This function in this node (Skeleton3D) can only be accessed from either the main thread or a thread group. Use call_deferred() instead.
  <C++ Error>    Condition "!is_readable_from_caller_thread()" is true. Returning: (Transform3D())
  <C++ Source>   scene/3d/node_3d.cpp:333 @ get_transform()
  <Stack Trace>  vrm_utils.gd:106 @ apply_node_transforms()
                 vrm_utils.gd:322 @ perform_retarget()
                 vrm_extension.gd:972 @ _import_post()
                 vrm_model_loader.gd:94 @ _load_model()
                 vrm_model_loader.gd:75 @ _load_models_threaded()

There are some points in vrm_utils.gd that modify the scene tree, causing this error to be thrown. I have not delved deep enough to see what impacts it may have (i.e., if it is ignorable), however it is a cause for concern.

I have attached an example Godot 4.2 project that demonstrates the error using the sample VRM models provided by the repository. The project will accept models drag and dropped and load multiple models sequentially in a background thread. On start-up, it will load both Alicia and Godette. The active model can be swapped with the left and right arrow keys.

vrm-model-viewer.zip

lyuma commented 1 month ago

creating scene chunks (nodes in tree arrangement) outside the active tree is fine

This is exactly what the code is written to do: The vrm loading code does not interact with the scene tree.

I tried on Godot 4.3 stable and I do not see the error.

Is it possible that the version of 4.2 you tried had a bug? I'd like to know if you can still reproduce this problem.

robertdhernandez commented 1 month ago

The warnings in the sample project appear when running Godot 4.2.2-stable but does not appear when running in Godot 4.3-stable.