Open GeTechG opened 4 days ago
I'll try to fix this case right away. But overall, this part still needs to be finished/improved in future versions (finding a simple but robust solution, especially for isolated threaded execution).
I tested on my side with similar logic but did not encounter this check. Could you please provide more details about the loader and loaded scene? Or directly debug your project in play mode with launch arguments like --path "YOUR_PROJECT_FULL_PATH" --verbose res://main.tscn
in your IDE/debugger.
My test case contains 2 scenes, and a script attached on each scene. main.tscn with MainControl.ts:
import { Error as GDError, Node2D, PackedScene, ResourceLoader } from "godot";
function load_scene_async(path: string) {
return new Promise<PackedScene | null>(resolve => {
let err = ResourceLoader.load_threaded_request(path, "", true);
console.log(path, GDError[err]);
let timerid: NodeJS.Timeout;
timerid = setInterval(() => {
let status = ResourceLoader.load_threaded_get_status(path);
if (status != ResourceLoader.ThreadLoadStatus.THREAD_LOAD_IN_PROGRESS) {
clearInterval(timerid);
if (status == ResourceLoader.ThreadLoadStatus.THREAD_LOAD_LOADED) {
resolve(<PackedScene>ResourceLoader.load(path));
} else {
resolve(null);
}
}
}, 20);
})
}
export default class MainControl extends Node2D {
async _ready() {
console.log(MainControl.name, "ready");
let path = "res://secondary.tscn";
let scene = await load_scene_async(path);
if (scene) {
let node = scene.instantiate();
this.add_child(node);
}
}
}
secondary.tscn with SecondaryControl.ts:
import { Node2D } from "godot";
export default class SecondaryControl extends Node2D {
_ready(): void {
console.log(SecondaryControl.name, "ready");
}
}
Hmm, I don't seem to see much difference, I also execute inside the promise, here is my code I specifically commented out that it falls on load
.
export default class AssetsPromiseLoader extends Node {
private promises: AssetsPromiseData[] = [];
public load(items: LoadItem[], onProgress?: ProgressCallback): Promise<any[]> {
return new Promise((resolve, reject) => {
for (let item of items) {
ResourceLoader.load_threaded_request(item.url, "", false);
}
this.promises.push({resolve, reject, items, onProgress});
});
}
_process(_delta: float64) {
// const deletePromises: number[] = [];
// for (let i = 0; i < this.promises.length; i++) {
// const data = this.promises[i];
// let loadedCount = 0;
// let fullProgress = 0;
// for (let item of data.items) {
// const progress = new GArray<number>();
// const status = ResourceLoader.load_threaded_get_status(item.url, progress);
// fullProgress += progress.get_indexed(0);
// switch (status) {
// case ResourceLoader.ThreadLoadStatus.THREAD_LOAD_INVALID_RESOURCE:
// data.reject(`Invalid resource: ${item.url}`);
// deletePromises.push(i);
// break;
// case ResourceLoader.ThreadLoadStatus.THREAD_LOAD_FAILED:
// data.reject(`Failed to load: ${item.url}`);
// deletePromises.push(i);
// break;
// case ResourceLoader.ThreadLoadStatus.THREAD_LOAD_LOADED:
// loadedCount++;
// break;
// }
// }
// if (data.onProgress) {
// data.onProgress(fullProgress / data.items.length);
// }
// if (loadedCount === data.items.length) {
// data.resolve(data.items.map(item => ResourceLoader.load_threaded_get(item.url)));
// deletePromises.push(i);
// }
// }
// this.promises = this.promises.filter((_, i) => !deletePromises.includes(i));
}
}
I also think there are no essential differences in the sample code. I'll try it again on other platforms. BTW, could you provide the stacktrace of the assertion failure by debugging your project in play mode (or from the log file of godot)? And are there any additional build options on your side for scons?
OS: linux (mint) If I understand how to run it correctly, that's all it gives me.
I don't use anything extra I have a clean build of godot 4.3. I build the editor like this:
scons platform=linuxbsd target=editor
I tried more platforms but still can't reproduce this problem (both on macos and linux mint 22, with godot branch 4.3 and tag 4.3-stable). However, it must be triggered by GodotJSScript::ensure_module_loaded()
unexpectedly from somewhere.
Can you debug from source via VSCode (or other IDE/debugger you have) to get the exact stacktrace of this assertion failure?
For VSCode, this godot docs may help. And for convenience, here is my config to debug in VSCode on Linux Mint:
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"group": "build",
"type": "shell",
"command": "scons",
"args": [
"p=linuxbsd",
// enable this if v8 not available
// "use_quickjs=yes",
"compiledb=yes",
"dev_build=yes",
"target=editor"
],
"problemMatcher": "$msCompile"
}
]
}
launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "CodeLLDB launch",
// path to your built godot executable file
"program": "${workspaceFolder}/bin/godot.linuxbsd.editor.dev.x86_64",
"args": [
"res://main.tscn",
"--rendering-driver", "opengl3",
"--path",
"!!!FULL_PATH_TO_YOUR_PROJECT!!!",
"--verbose"
],
"cwd": "!!!FULL_PATH_TO_YOUR_PROJECT!!!",
"externalConsole": false,
"preLaunchTask": "build"
}
]
}
The exact Call Stack
is available in Debug
in VSCode on the breakpoint of the assertion failure triggered.
I don't understand anything... I built as you have, I added a config for debug, I started godot to test and it worked, I checked on my old build also works, it somehow fixed itself, I'll try to look for something else, maybe I missed something.
I wanted to load resources in the background
but my game crashed, but boon was the message)
I'd like to ask how hard it is to add support, and if it can be done on the Godot side since thread execution is not required in GodotJs or am I missing something?