Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement an @export_lazy_resource export annotation #8484

Open
IntangibleMatter opened this issue Nov 21, 2023 · 8 comments
Open

Implement an @export_lazy_resource export annotation #8484

IntangibleMatter opened this issue Nov 21, 2023 · 8 comments

Comments

@IntangibleMatter
Copy link

IntangibleMatter commented Nov 21, 2023

Describe the project you are working on

A world with many deeply interconnected levels.

Describe the problem or limitation you are having in your project

My game has a lot of exits to other levels. Because these exits usually go both ways, they usually want to hold a reference to the other level. This causes a cyclic dependency, making both levels unopenable until you fix them in a text editor, removing the reference.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

@export_lazy_resource would export a reference to a resource, but not load it until requested by the script. This means that any sort of cyclic dependency issue that doesn’t actually require the resource to be loaded can be resolved, and the person writing the code can then manually use the resource however it might need the be used.

Additionally (though this is just one idea of how to handle it), there could be a new lazyload() function in the vein of load and preload, where it keeps a reference to the resource without actually loading it into memory.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

It would be used similarly to other export annotations, though likely with an optional type specifier. For example @export_lazy_resource(type: Resource) var next_scene.

Then, when you need to actually load the resource, you could pass it up to a higher node who actually does the loading, or you could use the fact that its reference to the current scene isn’t actually loaded, allowing you to do something like this:

@export_lazy_resource(PackedScene) var next_room = lazyload(“res://rooms/room_02.tscn”)

func load_next_room() -> void:
    # even though the scene is loaded, because it doesn’t actually load the reference to this scene because it also exported the resource as unloaded. 
    var room := load(next_room).instantiate()
    get_tree().change_scene_to_packedscene(room)

If this enhancement will not be used often, can it be worked around with a few lines of script?

This would be used frequently by many Godot users I suspect, as many level-based games want to maintain references to each other.

Currently I’m keeping a string as a path to the next room, but this is fallable, as a room could be renamed or moved. Another more robust solution can be seen here, but this is a bit ugly and not very convenient.

Is there a reason why this should be core and not an add-on in the asset library?

It involves core functionality around loading assets.

@IntangibleMatter IntangibleMatter changed the title Implement an @export_unloaded_resource export annotation. Implement an @export_lazy_resource export annotation. Nov 21, 2023
@Dorifor
Copy link

Dorifor commented Nov 21, 2023

Is there a reason for the type to be a param instead of just usual var scene: PackedScene ?

@IntangibleMatter
Copy link
Author

Is there a reason for the type to be a param instead of just usual var scene: PackedScene ?

I'm not sure. It made sense to me when writing it, but that might make more sense. That's why this is a proposal, community discussion.

@KoBeWi
Copy link
Member

KoBeWi commented Nov 21, 2023

I am not sure how feasible it is to implement. Even if you export lazy, the resource has to be listed in scene dependencies, which are automatically loaded with the scene. Deferring it would require some core changes to scene loader.

@AnidemDex
Copy link

I thought that PROPERTY_USAGE_DEFERRED_SET_RESOURCE usage was the scenario of this issue 🤔

@KoBeWi
Copy link
Member

KoBeWi commented Nov 21, 2023

PROPERTY_USAGE_DEFERRED_SET_RESOURCE was never implemented and is deprecated.
Also even if it was working as (presumably) intended, i.e. setting the property after everything else, that still does not affect the loading behavior.

@mrpedrobraga
Copy link

mrpedrobraga commented Nov 21, 2023

I am not sure how feasible it is to implement. Even if you export lazy, the resource has to be listed in scene dependencies, which are automatically loaded with the scene. Deferring it would require some core changes to scene loader.

Regarding the specific changes in core that need to be made when loading PackedScenes; at least from my perspective it doesn't seem to break compatibility or anything grotesque.

It'd require a sibling to PackedScene::_bundled.variants which can, perhaps, keep the external resource's path similar to how InstancePlaceholder does it for inherited scenes in a scene tree.

I went into a bit more depth in my proposal of what I think is the same thing (#8483). (Both proposals were made within hours of each other, so apparently @IntangibleMatter and I share a brain.)

@huwpascoe
Copy link

Created a plugin that may be helpful:
https://godotengine.org/asset-library/asset/3291

@Calinou Calinou changed the title Implement an @export_lazy_resource export annotation. Implement an @export_lazy_resource export annotation Oct 11, 2024
@KoBeWi
Copy link
Member

KoBeWi commented Oct 11, 2024

Looks like godotengine/godot#97912 will cover this. @export_path already exists, but that PR makes it "auto update" in case file is moved etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants