godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add an export option to explicitly include selected resources without dependencies #5992

Open SysError99 opened 1 year ago

SysError99 commented 1 year ago

Describe the project you are working on

Many of instant games that need to be shipped into web browser platforms.

Describe the problem or limitation you are having in your project

Godot game files are extremely heavy for web platforms, and only few cases that make Godot games acceptable to be put on browser, such as Itch.io, which most of players will have patience to wait for the game to load. Since I use Godot on instant games myself, letting the game to load all at once isn't a preferable option.

My current workflow has automated scripts that will export main game files along with separated PCK files, then those files will be downloaded on-demand, which helps saving lots of space and time to load.

However, as I discovered that Godot export options don't have any of resource options to be chosen that explicitly omit dependencies that already exist in main game files. It's not currently a problem if main game files don't have many of heavy dependencies, but it will definitely be a problem if Godot will be used in larger web browser projects.

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

Add an option that makes Godot explicitly omit file dependencies. image

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

In many cases that main game files already have all of files required for dependents to work properly. This will help reducing PCK/ZIP file size in cases that dependencies aren't needed to be updated.

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

I can make do with excluding files, directory options at the bottom of the window, but as I have many of PCK templates needed to be exported, it become cumbersome and tedious to make sure that all PCK files have omitted unnecessary files/directories.

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

This is direct change in the game engine's build process.

Calinou commented 1 year ago

This makes sense, but the documentation should carefully point out that you can't load scenes that don't have all their dependencies available. This means that all PCKs containing scene need to be loaded before you can attempt loading a scene.

SysError99 commented 1 year ago

This makes sense, but the documentation should carefully point out that you can't load scenes that don't have all their dependencies available. This means that all PCKs containing scene need to be loaded before you can attempt loading a scene.

This is definitely a case when I firstly attempted to omit registered script classes from PCK packages. It keeps complaining that it cannot find specified class and failed to load scripts. Making a warning on the editor while user chooses such option would be very viable too.

Red3Tango commented 1 year ago

This is exactly what I was wanting / looking for. The use-case I have been planning for is if you have Expansions (aka DLCs). With the current implementation in (4.0.1) is that you have to select everything you do NOT want included, which could be a lot, and harder to verify if its right. Yes this can cause issues with trying to load resources that are not present, but everything we do in programming can cause issues.

My current structure I have 3 main folders (that I use for separate PCK files) Core, Common, and Expansion. Core I have for Autoload scripts and initial entry to the program. Common contains, just that common resources that could be used in multiple areas (shaders, sounds, etc). Then Expansion has level(s) and specialty resources (and uses some resources from Common and Core.) With this structure it is not as hard to omit, however, would be extremely useful to have an Export ONLY selected resources (without dependencies) option instead of the Export all resources in the project except resources checked below. Yes this would essentially do the same thing, just the selection(s) would be inverted. (and believe to be easier to use and visually confirm accuracy)

ThatCoolCoder commented 1 year ago

I too would really benefit from this addition (albeit only if it was backported to version 3.x). EDIT: I moved my project to Godot 4.

I'm making a game that is heavily focused on creating and using mod content. Godot's tool to export .pck files containing only selected resources, and then load them in later seemed like exactly what I needed, but the forced inclusion of dependencies is a problem.

The mods will reference many assets from the base game, meaning that these assets will needlessly be included when packing mods. I looked inside a test mod .pck, and because it used a c# script from the base game, what appeared to be much of the .mono/ directory was included, down to the timestamps for when the script files were last edited. The content of project.godot was also included. I'm not sure if loading the pack would overwrite the settings, but if it does then there should be a way to avoid that. The overall effect was that 1mb of assets (scene, basic GLTF model and materials) created a 30mb resource pack.

Calinou commented 1 year ago

I too would really benefit from this addition (albeit only if it was backported to version 3.x).

Considering the export system has received heavy refactoring in 4.0, this is unlikely to be backported to 3.x if it's implemented in 4.x (unless it turns out to be trivial to implement).

As a workaround, look into writing a script that calls a PCK modification tool to remove dependencies from the PCK after it's created.

ThatCoolCoder commented 1 year ago

@Calinou that is a fair point, but given that this issue was raised when 3.x was still the latest stable version - presumably meaning that it was wanted in a project from 3.x - I feel that there is a case for implementing it in 3.x.

However, at the present time I will also look into the workaround you suggested, as well as investigating whether my project can be ported to 4.x.

ThatCoolCoder commented 1 year ago

I had a few spare hours today so I created an example implementation for 3.x - commits. It's an incomplete implementation in many ways (for instance it's not on 4.x, has no documentation and might not work when exporting from command line), but it shows that the basic functionality is not too difficult to create.

Unfortunately this did not reduce pck/zip size that much because in C# projects the .mono folder is still included, so if I have time I'll look into that.

Edit: it looks like it would be more difficult to exclude the C# stuff, since this is managed by an export plugin. The export plugins appear to always be called and are not expected to perform differently based on what resources are being exported (even though a script is technically a resource). This means that every export will contain the entire assembly + script metadata. I have not checked, but presumably all script data will be exported if using GDScript or any other language.

kaluluosi commented 8 months ago

I had figure it out. image

You can checkout this. https://github.com/kaluluosi/godot/tree/kaluluosi-4.2.1b

Or just download my build. https://github.com/kaluluosi/godot/releases/tag/4.2.1b

image

And this is the demo. game.zip patches.zip

Unzip them like this: image

That is how it works. image

Summer

We can't only add a new filter option to figure it out. Just has the filter, you still need to create lots of presets to pack each resource. And for other platform you should create them all again. Hundreds of presets in the export dialog may make it crash or make you insanity.

We need this too. Add support for exporting specific resources using the --export-pack command line argument #8748

Then you can create a base preset, like "Pack PCK". Use python or shell script.

godot --headless --export-pack "Pack PCK" --export-files <files split with comma> path/to/<save>.pck

This is my workflow for the demo above.

build_pck.py

"""
author:        kaluluosi111 <kaluluosi@gmail.com>
date:          2023-12-30 07:55:50
Copyright © Kaluluosi All rights reserved
"""
import json
import os
import glob
import posixpath as path
import hashlib
import subprocess
from concurrent import futures
from typing import List

def get_files():
    files = glob.glob("src/**/*.*", recursive=True)

    for file in files:
        if file.endswith(".import"):
            continue

        yield file

def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

patches_root = "dist/windows/patches"
# manifest for pck md5 version, use to diff changes
manifest = {}

def _task(file: str, hash_it: bool = False):
    file = file.replace("\\", "/")
    res_path = path.join("res://", file)
    dir = path.dirname(file)

    os.makedirs(path.join(patches_root, dir), exist_ok=True)

    # hash file name for confuse
    if hash_it:
        file = hashlib.md5(file.encode("utf-8")).hexdigest() + ".pck"

    export_path = path.join(patches_root, file + ".pck")
    subprocess.run(
        f'godot.bat --headless --export-pack "Windows Desktop PCK" --export-files {res_path}  {export_path}',
        stdout=subprocess.PIPE,
    )
    # record pck md5
    manifest[file] = md5(export_path)
    print("Pack:", res_path, "->", export_path)

print("Start Pack")

for file in get_files():
    _task(file)

manifest_file = open(os.path.join(patches_root, "manifest.json"), mode="w")
json.dump(manifest, manifest_file, ensure_ascii=False, indent=4)

print("End Pack")
Start Pack
Pack: res://src/assets/tilemap-backgrounds_packed.png -> dist/windows/patches/src/assets/tilemap-backgrounds_packed.png.pck
Pack: res://src/assets/tilemap-characters.png -> dist/windows/patches/src/assets/tilemap-characters.png.pck
Pack: res://src/assets/tilemap_packed.png -> dist/windows/patches/src/assets/tilemap_packed.png.pck
Pack: res://src/gameplay/start_position.gd -> dist/windows/patches/src/gameplay/start_position.gd.pck
Pack: res://src/gameplay/start_position.tscn -> dist/windows/patches/src/gameplay/start_position.tscn.pck
Pack: res://src/gameplay/box/box.gd -> dist/windows/patches/src/gameplay/box/box.gd.pck
Pack: res://src/gameplay/box/box.tscn -> dist/windows/patches/src/gameplay/box/box.tscn.pck
Pack: res://src/gameplay/camera/camera_2d.tscn -> dist/windows/patches/src/gameplay/camera/camera_2d.tscn.pck
Pack: res://src/gameplay/combat/destroybox.tscn -> dist/windows/patches/src/gameplay/combat/destroybox.tscn.pck
Pack: res://src/gameplay/combat/hammerbox.tscn -> dist/windows/patches/src/gameplay/combat/hammerbox.tscn.pck
Pack: res://src/gameplay/combat/hitbox.tscn -> dist/windows/patches/src/gameplay/combat/hitbox.tscn.pck
Pack: res://src/gameplay/combat/hurtbox.tscn -> dist/windows/patches/src/gameplay/combat/hurtbox.tscn.pck
Pack: res://src/gameplay/door/door.gd -> dist/windows/patches/src/gameplay/door/door.gd.pck
Pack: res://src/gameplay/door/door.tscn -> dist/windows/patches/src/gameplay/door/door.tscn.pck
Pack: res://src/gameplay/enemy/enemy.gd -> dist/windows/patches/src/gameplay/enemy/enemy.gd.pck
Pack: res://src/gameplay/enemy/enemy.tscn -> dist/windows/patches/src/gameplay/enemy/enemy.tscn.pck
Pack: res://src/gameplay/enemy/robot.gd -> dist/windows/patches/src/gameplay/enemy/robot.gd.pck
Pack: res://src/gameplay/enemy/robot.tscn -> dist/windows/patches/src/gameplay/enemy/robot.tscn.pck
Pack: res://src/gameplay/interactive/interactivebox.gd -> dist/windows/patches/src/gameplay/interactive/interactivebox.gd.pck
Pack: res://src/gameplay/interactive/interactivebox.tscn -> dist/windows/patches/src/gameplay/interactive/interactivebox.tscn.pck
Pack: res://src/gameplay/interactive/switch.gd -> dist/windows/patches/src/gameplay/interactive/switch.gd.pck
Pack: res://src/gameplay/interactive/switch.tscn -> dist/windows/patches/src/gameplay/interactive/switch.tscn.pck
Pack: res://src/gameplay/item/item.gd -> dist/windows/patches/src/gameplay/item/item.gd.pck
Pack: res://src/gameplay/item/item.tscn -> dist/windows/patches/src/gameplay/item/item.tscn.pck
Pack: res://src/gameplay/placeholder/placeholder.gd -> dist/windows/patches/src/gameplay/placeholder/placeholder.gd.pck
Pack: res://src/gameplay/placeholder/placeholder.tscn -> dist/windows/patches/src/gameplay/placeholder/placeholder.tscn.pck
Pack: res://src/gameplay/platform/platform.gd -> dist/windows/patches/src/gameplay/platform/platform.gd.pck
Pack: res://src/gameplay/platform/platform.tscn -> dist/windows/patches/src/gameplay/platform/platform.tscn.pck
Pack: res://src/gameplay/player/player.gd -> dist/windows/patches/src/gameplay/player/player.gd.pck
Pack: res://src/gameplay/player/player.tscn -> dist/windows/patches/src/gameplay/player/player.tscn.pck
Pack: res://src/gameplay/trigger/trigger.tscn -> dist/windows/patches/src/gameplay/trigger/trigger.tscn.pck
Pack: res://src/levels/main.tscn -> dist/windows/patches/src/levels/main.tscn.pck
Pack: res://src/manager/game.gd -> dist/windows/patches/src/manager/game.gd.pck
Pack: res://src/manager/game.tscn -> dist/windows/patches/src/manager/game.tscn.pck
Pack: res://src/manager/hud.gd -> dist/windows/patches/src/manager/hud.gd.pck
Pack: res://src/manager/hud.tscn -> dist/windows/patches/src/manager/hud.tscn.pck
Pack: res://src/manager/player_state.gd -> dist/windows/patches/src/manager/player_state.gd.pck
Pack: res://src/resources/backgrounds/background_01.tres -> dist/windows/patches/src/resources/backgrounds/background_01.tres.pck
Pack: res://src/resources/characters/ch_0001.tres -> dist/windows/patches/src/resources/characters/ch_0001.tres.pck
Pack: res://src/resources/characters/ch_0001.tscn -> dist/windows/patches/src/resources/characters/ch_0001.tscn.pck
Pack: res://src/resources/characters/ch_0002.tres -> dist/windows/patches/src/resources/characters/ch_0002.tres.pck
Pack: res://src/resources/characters/ch_0002.tscn -> dist/windows/patches/src/resources/characters/ch_0002.tscn.pck
Pack: res://src/resources/doors/door_01.tres -> dist/windows/patches/src/resources/doors/door_01.tres.pck
Pack: res://src/resources/doors/door_02.tres -> dist/windows/patches/src/resources/doors/door_02.tres.pck
Pack: res://src/resources/doors/door_03.tres -> dist/windows/patches/src/resources/doors/door_03.tres.pck
Pack: res://src/resources/enemies/robot_01.tres -> dist/windows/patches/src/resources/enemies/robot_01.tres.pck
Pack: res://src/resources/enemies/robot_01.tscn -> dist/windows/patches/src/resources/enemies/robot_01.tscn.pck
Pack: res://src/resources/enemies/robot_02.tres -> dist/windows/patches/src/resources/enemies/robot_02.tres.pck
Pack: res://src/resources/enemies/robot_02.tscn -> dist/windows/patches/src/resources/enemies/robot_02.tscn.pck
Pack: res://src/resources/enemies/robot_03.tres -> dist/windows/patches/src/resources/enemies/robot_03.tres.pck
Pack: res://src/resources/enemies/robot_03.tscn -> dist/windows/patches/src/resources/enemies/robot_03.tscn.pck
Pack: res://src/resources/enemies/robot_04.tres -> dist/windows/patches/src/resources/enemies/robot_04.tres.pck
Pack: res://src/resources/enemies/robot_04.tscn -> dist/windows/patches/src/resources/enemies/robot_04.tscn.pck
Pack: res://src/resources/platform/platform_01.tres -> dist/windows/patches/src/resources/platform/platform_01.tres.pck
Pack: res://src/resources/platform/platform_02.tres -> dist/windows/patches/src/resources/platform/platform_02.tres.pck
Pack: res://src/resources/platform/platform_03.tres -> dist/windows/patches/src/resources/platform/platform_03.tres.pck
Pack: res://src/resources/prop/brick_big.tres -> dist/windows/patches/src/resources/prop/brick_big.tres.pck
Pack: res://src/resources/prop/brick_box.tres -> dist/windows/patches/src/resources/prop/brick_box.tres.pck
Pack: res://src/resources/prop/brick_small.tres -> dist/windows/patches/src/resources/prop/brick_small.tres.pck
Pack: res://src/resources/prop/button.tres -> dist/windows/patches/src/resources/prop/button.tres.pck
Pack: res://src/resources/prop/coin.tres -> dist/windows/patches/src/resources/prop/coin.tres.pck
Pack: res://src/resources/prop/coin_box.tres -> dist/windows/patches/src/resources/prop/coin_box.tres.pck
Pack: res://src/resources/prop/coin_box_empty.tres -> dist/windows/patches/src/resources/prop/coin_box_empty.tres.pck
Pack: res://src/resources/prop/diamon.tres -> dist/windows/patches/src/resources/prop/diamon.tres.pck
Pack: res://src/resources/prop/iron_box.tres -> dist/windows/patches/src/resources/prop/iron_box.tres.pck
Pack: res://src/resources/prop/iron_box_empty.tres -> dist/windows/patches/src/resources/prop/iron_box_empty.tres.pck
Pack: res://src/resources/prop/item_box.tres -> dist/windows/patches/src/resources/prop/item_box.tres.pck
Pack: res://src/resources/prop/item_box_empty.tres -> dist/windows/patches/src/resources/prop/item_box_empty.tres.pck
Pack: res://src/resources/prop/key.tres -> dist/windows/patches/src/resources/prop/key.tres.pck
Pack: res://src/resources/prop/launcher.tres -> dist/windows/patches/src/resources/prop/launcher.tres.pck
Pack: res://src/resources/prop/lock_box.tres -> dist/windows/patches/src/resources/prop/lock_box.tres.pck
Pack: res://src/resources/prop/pin.tres -> dist/windows/patches/src/resources/prop/pin.tres.pck
Pack: res://src/resources/prop/switch.tres -> dist/windows/patches/src/resources/prop/switch.tres.pck
Pack: res://src/resources/prop/trap.tres -> dist/windows/patches/src/resources/prop/trap.tres.pck
Pack: res://src/resources/prop/tree.tres -> dist/windows/patches/src/resources/prop/tree.tres.pck
Pack: res://src/resources/prop/wood_box.tres -> dist/windows/patches/src/resources/prop/wood_box.tres.pck
Pack: res://src/resources/tiles/tilemap.tres -> dist/windows/patches/src/resources/tiles/tilemap.tres.pck
Pack: res://src/scenes/boxies/brick_box.gd -> dist/windows/patches/src/scenes/boxies/brick_box.gd.pck
Pack: res://src/scenes/boxies/brick_box.tscn -> dist/windows/patches/src/scenes/boxies/brick_box.tscn.pck
Pack: res://src/scenes/boxies/coin_box.gd -> dist/windows/patches/src/scenes/boxies/coin_box.gd.pck
Pack: res://src/scenes/boxies/coin_box.tscn -> dist/windows/patches/src/scenes/boxies/coin_box.tscn.pck
Pack: res://src/scenes/boxies/iron_box.gd -> dist/windows/patches/src/scenes/boxies/iron_box.gd.pck
Pack: res://src/scenes/boxies/iron_box.tscn -> dist/windows/patches/src/scenes/boxies/iron_box.tscn.pck
Pack: res://src/scenes/boxies/item_box.gd -> dist/windows/patches/src/scenes/boxies/item_box.gd.pck
Pack: res://src/scenes/boxies/item_box.tscn -> dist/windows/patches/src/scenes/boxies/item_box.tscn.pck
Pack: res://src/scenes/boxies/lock_box.gd -> dist/windows/patches/src/scenes/boxies/lock_box.gd.pck
Pack: res://src/scenes/boxies/lock_box.tscn -> dist/windows/patches/src/scenes/boxies/lock_box.tscn.pck
Pack: res://src/scenes/doors/door.tscn -> dist/windows/patches/src/scenes/doors/door.tscn.pck
Pack: res://src/scenes/enemy/e_0001_0.tscn -> dist/windows/patches/src/scenes/enemy/e_0001_0.tscn.pck
Pack: res://src/scenes/enemy/e_0002_0.tscn -> dist/windows/patches/src/scenes/enemy/e_0002_0.tscn.pck
Pack: res://src/scenes/enemy/e_0003_0.gd -> dist/windows/patches/src/scenes/enemy/e_0003_0.gd.pck
Pack: res://src/scenes/enemy/e_0003_0.tscn -> dist/windows/patches/src/scenes/enemy/e_0003_0.tscn.pck
Pack: res://src/scenes/fx/enemy_die_fx.tscn -> dist/windows/patches/src/scenes/fx/enemy_die_fx.tscn.pck
Pack: res://src/scenes/fx/explosion_brick.tscn -> dist/windows/patches/src/scenes/fx/explosion_brick.tscn.pck
Pack: res://src/scenes/fx/player_die_fx.tscn -> dist/windows/patches/src/scenes/fx/player_die_fx.tscn.pck
Pack: res://src/scenes/interactive/switch.gd -> dist/windows/patches/src/scenes/interactive/switch.gd.pck
Pack: res://src/scenes/interactive/switch.tscn -> dist/windows/patches/src/scenes/interactive/switch.tscn.pck
Pack: res://src/scenes/interactive/wood_box.gd -> dist/windows/patches/src/scenes/interactive/wood_box.gd.pck
Pack: res://src/scenes/interactive/wood_box.tscn -> dist/windows/patches/src/scenes/interactive/wood_box.tscn.pck
Pack: res://src/scenes/item/coin.tscn -> dist/windows/patches/src/scenes/item/coin.tscn.pck
Pack: res://src/scenes/item/diamon.tscn -> dist/windows/patches/src/scenes/item/diamon.tscn.pck
Pack: res://src/scenes/item/key.gd -> dist/windows/patches/src/scenes/item/key.gd.pck
Pack: res://src/scenes/item/key.tscn -> dist/windows/patches/src/scenes/item/key.tscn.pck
Pack: res://src/scenes/level/level.gd -> dist/windows/patches/src/scenes/level/level.gd.pck
Pack: res://src/scenes/parallaxies/parallax_background_01.tscn -> dist/windows/patches/src/scenes/parallaxies/parallax_background_01.tscn.pck
Pack: res://src/scenes/platforms/ladder.gd -> dist/windows/patches/src/scenes/platforms/ladder.gd.pck
Pack: res://src/scenes/platforms/ladder.tscn -> dist/windows/patches/src/scenes/platforms/ladder.tscn.pck
Pack: res://src/scenes/platforms/platform.tscn -> dist/windows/patches/src/scenes/platforms/platform.tscn.pck
Pack: res://src/scenes/player/h_0001.tscn -> dist/windows/patches/src/scenes/player/h_0001.tscn.pck
Pack: res://src/scenes/player/h_0002.tscn -> dist/windows/patches/src/scenes/player/h_0002.tscn.pck
Pack: res://src/scenes/trigger/launcher.gd -> dist/windows/patches/src/scenes/trigger/launcher.gd.pck
Pack: res://src/scenes/trigger/launcher.tscn -> dist/windows/patches/src/scenes/trigger/launcher.tscn.pck
Pack: res://src/scenes/trigger/trigger_btn.gd -> dist/windows/patches/src/scenes/trigger/trigger_btn.gd.pck
Pack: res://src/scenes/trigger/trigger_btn.tscn -> dist/windows/patches/src/scenes/trigger/trigger_btn.tscn.pck
Pack: res://src/scenes/ui/game_over/game_over.gd -> dist/windows/patches/src/scenes/ui/game_over/game_over.gd.pck
Pack: res://src/scenes/ui/game_over/game_over.tscn -> dist/windows/patches/src/scenes/ui/game_over/game_over.tscn.pck
Pack: res://src/scenes/ui/main_menu/main_menu.gd -> dist/windows/patches/src/scenes/ui/main_menu/main_menu.gd.pck
Pack: res://src/scenes/ui/main_menu/main_menu.tscn -> dist/windows/patches/src/scenes/ui/main_menu/main_menu.tscn.pck
Pack: res://src/scenes/ui/pause_menu/pause_menu.gd -> dist/windows/patches/src/scenes/ui/pause_menu/pause_menu.gd.pck
Pack: res://src/scenes/ui/pause_menu/pause_menu.tscn -> dist/windows/patches/src/scenes/ui/pause_menu/pause_menu.tscn.pck
Pack: res://src/scenes/ui/transition/fade_in_out.gd -> dist/windows/patches/src/scenes/ui/transition/fade_in_out.gd.pck
Pack: res://src/scenes/ui/transition/fade_in_out.tscn -> dist/windows/patches/src/scenes/ui/transition/fade_in_out.tscn.pck
Pack: res://src/scenes/ui/transition/transition_mgr.gd -> dist/windows/patches/src/scenes/ui/transition/transition_mgr.gd.pck
Pack: res://src/scenes/ui/transition/transition_mgr.tscn -> dist/windows/patches/src/scenes/ui/transition/transition_mgr.tscn.pck
Pack: res://src/test/node.gd -> dist/windows/patches/src/test/node.gd.pck
Pack: res://src/test/test_01.tscn -> dist/windows/patches/src/test/test_01.tscn.pck
Pack: res://src/test/test_02.tscn -> dist/windows/patches/src/test/test_02.tscn.pck
Pack: res://src/test/test_03.tscn -> dist/windows/patches/src/test/test_03.tscn.pck
End Pack

One more thing about the dependencies

If you don't need load dyanmic in runtime ,just like my demo download and load all on startup, you don't need to deal with the dependencies. For me , pack PCK independently just use to archive Hot/Incremental Update, I don't dynamic download and load new PCK while player playing game.

If you do need to load dyanmic while playing.

There is very easy to export dependencies map of each resources and save it as json file. That means if you want to dynamic load a PCK in runtime and no lose of dependencies of other PCK. You can just search the dependencies map find out witch pck it depend on and load them before. While resource load fail, then try to download PCK and its dependencies.

Export resource without dependency means the PCK is only chunk, it's not a entirety useable PCK. It must be loaded together with other dependent PCKs to work. And programmer should handle it themself.

kaluluosi commented 8 months ago

@Calinou that is a fair point, but given that this issue was raised when 3.x was still the latest stable version - presumably meaning that it was wanted in a project from 3.x - I feel that there is a case for implementing it in 3.x.

However, at the present time I will also look into the workaround you suggested, as well as investigating whether my project can be ported to 4.x.

If your project hard to leave 3.x. You can try godotpcktool . It can extract PCK and pack it back(only supports 3.x). I'm not sure it works for you.