Image Failed to Load - Custom Loading UI

I have a custom loading UI for my game that revolves around loading in custom images. The scripting itself works but the images fail to load. Before I show the error codes and what the UI looks like:

  • Yes, I’ve looked around the DevForum for answers and found none.
  • Yes, I’ve tried preloading the image Id using the content provider, first thing on the server when loading.
  • The game is a group game and yes, I’ve added the image Id’s corresponding to the group, not my inventory.
  • I’m not sure if it’s the asset Id directly because I’ve tried copying the rbxassetid string into an image and using the outputted id.
  • Is it because it’s the loading UI and the content provider does not handle images that early into loading?

Error:
https://gyazo.com/9218a2e48179be2152b6a56aa7119690

Loading Screen w/out Image:
https://gyazo.com/c3c2ddd2a80a81ac14f9f9a37314c109

Code:
Server:

local preloadImageIds = {"3099843685","3099843935","3099844218","3099844451","3099844690"};
spawn(function() game:GetService("ContentProvider"):PreloadAsync(preloadImageIds); end)

Client (Located in Replicated First):

local imageIds = {"rbxassetid://3099843685","rbxassetid://3099843935","rbxassetid://3099844218","rbxassetid://3099844451","rbxassetid://3099844690"};

imageBox.Image = imageIds[math.random(1,#imageIds)];

-- Separate here for unimportant code

while checkGame() == false do
	imageBox.Image = imageIds[math.random(1,#imageIds)];
	
	wait(math.random(5,10));
end

Any help or suggestions would be appreciated. Thank you.

When you manually copy/paste the image ID into a decal/image label, does it load? If it doesn’t, you may have gotten the image IDs from a bad source (copy/pasting from the address bar on the website doesn’t work–try dropping the image from your inventory into the game as a decal and copying that ID instead.)

I also don’t think PreloadAsync() works like that. Based on this article, you need to pass in instances containing the IDs, not the IDs themselves.

As I stated above, yes I already tried that. Thank you for the article, I’ll fix that ASAP.

This is a very inefficient way to preload assets. I recommend using a loop to loop through all assets and check if they are a type of asset you can preload

local assets = {}

local function scan(object)
    if object:IsA("ImageLabel") or object:IsA("ImageButton") then
        assets[#assets + 1] = object
    end
    
    for i, child in pairs(object:GetChildren()) do --You can also use GetDescendants
        scan(child)
    end
end

scan(workspace)
scan(starterGui)

And then just do contentProvider:PreloadAsync(assets)

You’re getting a failed to load error because you’re trying to set the Image property of an ImageLabel with a decal asset ID. You need to convert the decal asset to an image asset, which is most easily done by right clicking the decal in Toolbox, and by selecting “Copy Asset Id”, which you can then replace all of your existing IDs with in your preloadImageIds table.

For instance, one of your decal assets “3099844218” converts to “3099844212”, which is an image asset.

Also, preloading those image IDs in a server script does not preload them for everyone’s client as far as I know, so you need to run PreloadAsync in a client script instead in order to effectively preload assets.

Additionally,

This is right, and you need to pass in instances to PreloadAsync instead. If you don’t want all of the assets you wish to preload to exist in the game already, and you just want them to be preloaded, you can try something this:

local ContentProvider = game:GetService('ContentProvider')

local Assets = {
	-- Instance Class, Property, Asset Id
	{"ImageLabel","Image",3119571284}
}

for AssetType,AssetInfo in pairs(Assets) do
	local AssetInstance = Instance.new(AssetInfo[1])
	AssetInstance[AssetInfo[2]] = "rbxassetid://"..AssetInfo[3]
	print('Preloading:',AssetInfo[3])
	ContentProvider:PreloadAsync({AssetInstance})
	print('Asset preloaded!',AssetInfo[3])
	AssetInstance:Destroy()
end
5 Likes

…? What? How? Your method is far more computationally expensive since it recurses through descendants of objects (which can slow down depending on how many objects are being gone through). OP’s method is simply passing a table of images to be prioritised in the preload queue.

In addition to the above, your examples are fairly poor. Preload should only be used on assets you need to be seen immediately, not on entire containers. Furthermore, passing an object through PreloadAsync also passes its descendants automatically, so a recursive function is pointless in its entirety.

That being said, @snorebear, the server should not be using the ContentProvider service because there is no assets that it needs to load. Downloading of assets is done by the client. Instead of setting the image of an ImageLabel to an image to “load” it, just put the preloading on the client.

2 Likes

A little something I’d like to point out: this only applies for non-image asset ids. The old behaviour of PreloadAsync is still preserved; if you pass in an asset url, it will be treated as an image and attempt to download it as such. Canonically however, you should be passing instances through PreloadAsync and not relying on that legacy behaviour.

Otherwise, you got it. :+1:

1 Like