$sprite.texture=load(path) not working on Android

Godot Version

4.2.1

Question

In a follow-up to a topic from 2020 …
How to get Android to recognize images - Archive - Godot Forum (godotengine.org)

I’m having a similar issue.
My game dynamically changes the texture of a sprite MULTIPLE times throughout the game. On PC, it works perfectly. However, when I tried to port it to Android, the dynamically loaded images are NOT showing up. All the images are in the same subfolder, so I can verify that some are showing, but not all. Is there some Android tweek I need to make to standard .load(path) line?
On PC…


vs on Android

When you export the game the original files (png, tscn, wav, ogg,…) aren’t exported directly but only the .remap (in the case of text resources that get compressed to binary: tscn, tres,…) or the .import files are (which point to the correct remapped/imported file inside the .godot folder).

DirAccess and FileAccess just read the directory/file directly and don’t take those files into account (it won’t follow the remap or import target file)

When running form the editor it’s looks fine because both files are present (the .import and the original file) But when running it in a exported project it won’t work.

You need to remove the extension .import or .remap like for example:

if file.get_extension() == "import":
	file = file.replace(".import", "")
1 Like

So I kinda understand what you’re talking about from when I unzipped the APK to see if my images were there.

I saw the .godot/imported folder with its ctex files as well as the regular image folder with its .import files which point to the ctex files.

What I’m NOT understanding is how stripping the .import off these text files would translate to images appearing when the import files “should be” remapping my call to the renamed and moved images.

Also, where in my code should that if statement appear? My path is directly to the image in question. There’s no “file selection” interaction with the user.

As an example:

const pokemart_textures = [“res://pokemerge/pokemart01_64.png”,
“res://pokemerge/pokemart02_64.png”]
series[“pokemart”] = pokemart_textures
$game_piece.texture=load(series[“pokemart”][0])

I assumed you were using DirAccess and FileAccess to list the files as you said that you were dynamically loading images.

Make sure that the paths are correct and are using the same casing.

If the paths are correct and you are still having issues, enable Deploy with Remote Debug under the Debug menu and, with the android phone correctly connected to the computer, launch the game from the editor from here:

image

(I don’t have a phone connected in the image but you should see your own one)

See if you have any errors or warnings in the Output or Debug docks.

NoRemoteExportPresets

But I DO have export presets configured with debug…

What am I doing wrong?

Check this documentation page One-click deploy — Godot Engine (stable) documentation in English to check that everything is setup correctly.

As with most of the documentation I’ve been reading in Godot, there’s a LOT to be desired as far as clear explanations to the novice Godot user.

One-click deploy is a feature that is available once a platform is properly configured and a supported device is connected to the computer. Since things can go wrong at many levels (platform may not be configured correctly, SDK may be incorrectly installed, device may be improperly configured, etc.), it’s good to let the user know that it exists.

It then points to the Export to Android page which I’ve been following to get as far as I’ve gotten.
I double checked the SDK Manager and saw some discrepancies from that list so I installed those.
… The guide says “SDK Platform 33”. The SDK Manager says version 35, but the actually download was “Platform 29 (revision 5)”. Is this making any sense?
… Rerunning the Android build produced DIFFERENT apksigning errors.

One-click deploy is only available once you’ve added an export template marked as Runnable in the Export dialog.

As I showed above, I have 2 exports marked as “runnable”: Windows and Android. I’ve made a Windows version and an Android version which installs and runs on my phone (except for this image glitch). Neither runnable export are activating the “One-Click Deploy” button. You’d think that the Windows One-Click would be the easiest to configure since that’s native and “always connected”, but even that isn’t available for this “feature”. This would seem to mean that it’s NOT configured correctly, but there’s no indicator of what configuration item is incorrect.

After adding an Android export preset marked as Runnable, Godot can detect when a USB device is connected to the computer and offer the user to automatically export, install and run the project (in debug mode) on the device.

No, that’s NOT what happens when I connect my phone to the PC. Literally NOTHING happens. Yes, my phone is in USB Debugging mode.

I’ve been working with Android Studio to see if I can get the problem corrected over there before confirming it in Godot. Still no dice.

I updated all the USB Drivers (latest is from 2020). Nothing.

I can see it in adb devices, but it says that it’s in off-line mode. Offline, in this case, means that it’s not responding to the adb server.

Near as I can tell, it’s because it’s “carrier-locked”. No, I’m not going to jailbreak my phone. I’ll try a different / older phone here that the kids have been playing with.

You are confusing the SDK platform with the SDK platform tools
In the SDK platforms tab select Android 13.0 ("Tiramisu") with API level 33
In the SDK tools tab enable Show package details at the bottom right of the list and select the versions the documentation says for each entry.

This has nothing to do with Godot, that’s how Android works.

You missed the Supported platforms section in the one-click deploy documentation page. Only Android and HTML5 are supported with iOS as planned to support. Other platforms can be tested and exported easily from the editor so there’s no need to have this functionality.

If the device does not show up in the adb devices list or it’s not working with adb Godot can’t do anything else. It uses adb to communicate with the phone. Again, not an issue Godot can fix. It’s part of the Android ecosystem.

I uninstalled and reinstalled my phone drivers using this guide:
Android Won’t Connect to Windows Over ADB? How to Fix in 3 Easy Steps (makeuseof.com)

I can now see my phone in Android Studio AND the One-Click icon!!!

One-Click_Deploy

No jailbreaking or anything else was done to my phone. Just replaced the drivers in Windows.

Running it via One-Click Deploy revealed this error…

E 0:00:06:0630 game_piece.gd:216 @ increment_texture(): No loader found for resource: res://pokemerge/game01_64.png (expected type: )
<C++ Error> Method/function failed. Returning: Ref()
<C++ Source> core/io/resource_loader.cpp:282 @ _load()
game_piece.gd:216 @ increment_texture()
game_board.gd:128 @ make_piece()
game_board.gd:60 @ _ready()

It’s the exact line I quoted above.
This error is repeated 70+ times because there are 70+ game pieces that are affected and are left without a texture.

I get the same no-images issue when I deploy in HTML so fixing one deployment would help figure out how to fix the other.

Again, make sure that the path is correct and they are using the same casing. For example, if the folder is Pokemerge (with an uppercase p) then the path should be res://Pokemerge/game01_64.png

If they are correct then post the complete code. Maybe somebody can spot the issue then.

All my files are on Git @ Godot-Project-Backup/Merge_Prim at main · TesFalcon/Godot-Project-Backup · GitHub

===================================================================
You had a bit of confusion above when I used the term “dynamically”. Let me explain…
Dynamic is the opposite of static. The 1st definition of Dynamic = “(of a process or system) characterized by constant change, activity, or progress”. By contrast, the 1st definition of Static = “lacking in movement, action, or change, especially in a way viewed as undesirable or uninteresting”

Prior to game time, there is 1 cell with a static texture, and there is 1 game_piece with a pre-set texture. At game time, I use the variable height and width to determine the size of the game_board and thus the maximum number of cells that will be instatiated. In the beginning, I used a small board of 2x2 to make reading the debugging comments easier to follow. The present board is 7x9. Later iterations of the game will change the size and shape of the game board. As seen in the images above, my dynamically generated game_board with static imaged cells are fine.

Once the game_board is made, the game_pieces are also made = the maximum number for cells. Unlike the game_cells, the pieces have their textures applied and changed at run-time (dynamically). In the present iteration of the game, there are 15 families of textures with 4 - 11 images in a given family for a total of 251 possible textures that could be applied to the piece at run-time. This will GROW in later iterations of the game.

The reference to these families of images are stored in separate arrays which are all combined into a dictionary of arrays named by the family. (My code example above demonstrated that.) Thus I only need to check 2 basic pieces of information to know which image to load at run-time: family (string) and texture_index (integer). Since the index is an integer, I can walk through the textures in the family by simply incrementing that index up to the maximum for that family image array.

As you stated above in your initial response, when the project gets packaged for distribution, the images are renamed and moved. Thus my static reference to res://pokemerge/game01_64.png becomes broken. Apparently, EVERY packaging and distribution of the game breaks this static reference in some way since it also breaks in distribution to HTML. The only reason it didn’t “break” as noticeably on Windows is because I was able to add the Pokemerge image folder to the .zip along with the .exe, but without that folder being added, the same issue happens.

=====================================================================

FYI, It’s a merge game. Two pieces that look alike are able to “merge” together. One piece has its texture incremented to the next texture in the family. The other piece is released from memory and disappears.

As you merge pieces together, certain pieces in certain families become “generators” and, when clicked, produce NEW pieces depending on the family that the generator exists in and a bit of randomness between common and uncommon family generation.

The entire object of the game is to generate ALL of the images in all of the families with various incentives to encourage the player to keep clicking and merging. My 13 yr old played / tested it for over an hour, and at the end said, “That was FUN! Get that on my phone!”

Again, for the 3rd time, make sure that the path is correct and they are using the same casing

You are using res://pokemerge/pokemart01_64.png but the folder is called PokeMerge so it will break when you export the game. load() is case sensitive when exporting the project to any platform.

It seems very odd to me that load() would be case in-sensitive when running locally but case sensitive when exporting.

Change made.

Tested on Android. Success.

Tested on HTML. Success.

Thank you.