How to properly use RequestQueueSize?

Howdy! I’m currently developing a custom loading screen for a game. I have the GUI created and all that good stuff, but I’m currently having trouble figuring out how I should properly utilize RequestQueueSize using the ContentProvider service. With that being said, I have a few questions in mind.

Here’s what I want to know

  • How long should I wait for RequestQueueSize while using a custom loading screen?
  • What are some proper usage cases for RequestQueueSize?
  • Is an example like the Developer Hub’s example on RequestQueueSize reliable?
1 Like

I wouldn’t use RequestQueueSize for a custom loading screen if I were preloading assets. I would load assets and once an asset is loaded, set the size of the loading bar. An example of this is:

local contentProvider = game:GetService('ContentProvider')
local assetsToLoad 

for i = 1,#assetsToLoad do
   local asset = assetsToLoad[i]
   contentProvider:PreloadAsync{asset}
   bar.Size = UDim2.new(i/#assetsToLoad,0,1,0)
end

You can create something similar with RequestQueueSize, by requesting the queue size every so often. It can be written like so:

local contentProvider = game:GetService('ContentProvider')
local assetsToLoad 

contentProvider:PreloadAsync(assetsToLoad)
local originalSize = contentProvider.RequestQueueSize

local function update()
   local n =  contentProvider.RequestQueueSize
   if n > 1 then
      return true
   else
      bar.Size = UDim2.new(n/originalSize,0,1,0)
   end
end

--Connect it up to a loop

I’m not entirely sure of a use-case for it, besides a loading screen. Also, do you mean how long you should wait until RequestQueueSize is 0?

2 Likes

Honestly, you shouldn’t be using RequestQueueSize, period. Your first solution works fine enough. Not only is RequestQueueSize an arbitrary value (thus your second solution produces inaccurate results regardless), but there are countless issues from technical to UX and beyond that are involved in its use.

PreloadAsync is the way to go, as is only running it on the assets that should be visible immediately. The client can stream the rest of asset downloading in the background while the game runs.

There’s frankly no use case for reading from RQS or using it as a value for your loading screens. It should just stay as a property that you can access to see how many assets are preparing to download but that’s about it. The Shift + F3 menu also shows RQS for debugging purposes (?).

1 Like

Worth noting as well: please don’t use PreloadAsync of 1 asset in a loop.

The correct way to do this is:

  • Create a table with all assets/instances you need to preload (note that PreloadAsync assumes that the content id arguments are images; if you need to preload sounds/meshes/etc. you need to specify instances that carry the required data
  • Call PreloadAsync once with the table
  • Use the recently added callbackFunction argument of PreloadAsync to monitor progress and update progress bars.

Calling PreloadAsync one asset at a time serializes the loading of assets, whereas PreloadAsync of the entire table will do asset load in parallel which can be much faster especially if assets aren’t in the on-disk cache.

16 Likes

For specifying instances such as sounds, meshes, etc. could GetDescendants() be used on already existing instances, or would it be better to preload assets and parent them to existing instances?

1 Like

PreloadAsync will do descendant traversal for you actually, so if you have a UI that you want to preload you can do PreloadAsync on the ScreenGui or something like that.

5 Likes

Creating unnecessary instances just to specify content type bothers me more than it should.

The API for this was also changed without warning a long while back and caused old versions of my game to stop working.

I recall that there was a callbackFunction added to PreloadAsync some time ago but there was never any announcement about it nor documentation posted about it (about to go file a documentation request).

With that being said though, how are you able to track progress? As far as I’m aware, the function fires for each item in the list but there’s no way to get a guaranteed size. When PreloadAsync traverses descendants, the array expands.

There was an important reason for this, which has to do with fixing moderation exploits. And the idea is that you don’t need to create new instances - you can often use instances that you already have.

You could use an infinite-scrolling progress bar (and if you need a counter, just count upwards) :slight_smile: But yeah the total count isn’t known unless you want to count the number of descendants and deduplicate the ids in the result…

1 Like

That’s a bit of a yikes from me. I was hoping that we’d be able to get the known number of assets to make an accurate progress bar and I don’t know how I feel about traversing more than once or using upwards arbitrary progress trackers like that…

I generally create the instance once the asset has finished loading, so my game ends up creating dozens of temporary instances in some cases. Is it possible to reuse these temporary instances and their tables for separate Preload calls that may be running at the same time? or is the instance and table referenced internally until the request completes/fails?
(sorry this isn’t quite on-topic)

I’ve had cases where I preloaded rbxassetid://12345678, but it came back as https://assetdelivery.roblox.com/v1/asset/?id=12345678, so comparing the ID with anything isn’t necessarily reliable.

1 Like

Yeah, the only way to get this data reliably would be to have the callback return some sort of progress indicator in addition to the status of the asset.

1 Like