Search code examples
luarobloxluaulua-5.1roblox-studio

Roblox Luau - Asset refuses to load in-game, but works in studio


In attempting to make a game, I'm trying to add music to it that plays when the game is loaded. Unfortunately, for some reason, in the actual game it refuses to load in more often than not, as is evident when I use ContentProvider:PreloadAsync();

local Attempt = true

while Attempt do
    ContentProvider:PreloadAsync({DayTheme},function(assetId,assetFetch)
        print("Got DayTheme with asset ID",assetId)
        if assetFetch == Enum.AssetFetchStatus.None then
            warn("DayTheme returned no valid information, and the engine didn't attempt to load it.")
        elseif assetFetch == Enum.AssetFetchStatus.Failure then
            warn("DayTheme failed to load and was aborted by the engine.")
        elseif assetFetch == Enum.AssetFetchStatus.Loading then return elseif assetFetch == Enum.AssetFetchStatus.TimedOut then
            print("Load timed out, trying again.")
        else
            print("ContentProvider returned OK")
            if not DayTheme.IsLoaded then
                print("Waiting for DayTheme to load")
                local pass = 1
                repeat
                    task.wait(1)
                    pass = pass + 1
                    print(pass)
                until DayTheme.IsLoaded or pass == 10
                if not DayTheme.IsLoaded then warn("DayTheme failed to load") else
                    if not DayTheme.IsPlaying then print("Playing"); DayTheme:Play() end
                end
            else
                if not DayTheme.IsPlaying then print("Playing"); DayTheme:Play() end
            end
            Attempt = false
        end
    end)
    task.wait(3)
end

Where DayTheme is a Sound instance (not an asset ID), running this section either 1) prints the "DayTheme failed to load and was aborted by the engine" warning I have set for Enum.AssetFetchStatus.Failure, or 2) eventually prints the "DayTheme failed to load" warning I have set for the DayTheme.IsLoaded check after ContentProvider returns Enum.AssetFetchStatus.Success. This is set up in a while loop to hopefully make it retry, since automatic retrying simply isn't a thing since around 2017.

It should also be said that this is not the standard "Failed to download asset" error that usually gets thrown around; no actual error is being provided by the game, and if it wasn't for the above code, I wouldn't have known that it fails to load as it just never plays. I have no idea why this is failing to preload, or how I can get it to load (or retry loading without such loops), and thus have no possible way of having music play in my game.

Other things to note;

  1. The audio I'm playing originates from ReplicatedStorage, but gets :Clone()'d out and placed into a folder in Workspace. I have multiple checks to ensure that it isn't returning nil, and that the instance does exist.
  2. The script itself is a LocalScript placed into StarterPlayerScripts. This still happens even if I move the script to a place like ReplicatedFirst.
  3. In Studio, the Sound asset loads perfectly fine without problems. On a very rare occasion (1/20 times was the most often I've gotten it to load), it will load in-game; otherwise, it's only in the actual game that it fails loading.
  4. The audio asset is owned by me, and thus the game does have permission to use it. This isn't a permissions problem.

So far, nobody else I've sent/made this or a similar post to has been able to assist me. There is [one post on the Roblox DevForum](https://devforum.roblox.com/t/failed-to-load-assets-should-automatically-retry/2037387/4?u=ladyterrene\] that mentions a potential fix, but this proved fruitless overall as it simply continues to fail.

I've tried everything I can think of, including:

  • programmatically creating, cloning, and changing the ID of the Sound instance to load the asset;
  • changing the locations of the asset in-game (e.g., moving it from ReplicatedStorage into Workspace;
  • attempting to iterate over ContentProvider:PreloadAsync() (as shown above);

but regardless of what it is I attempt, in some way, shape, or form the asset fails loading and, eventually, hits my own custom timeout limit.

Ideally, this should be contained within a LocalScript, as I want this to be per-player and not the server overall.


Solution

  • I want to give you two links that are related to your issue and an explanation: https://devforum.roblox.com/t/isloaded-is-intermittently-returning-false-for-successfully-loaded-audio/2809379 https://create.roblox.com/docs/reference/engine/classes/ContentProvider#RequestQueueSize In the last link I linked, it says the following:

    Developers are advised not to use RequestQueueSize to create loading bars. This is because the queue size can both increase and decrease over time as new assets are added and downloaded. Developers looking to display loading progress should load assets one at a time (see example below).

    This means that certain assets may be re-added to the queue if necessary, which means that the code for your callback may run twice inside, that could be a possible cause of your error.

    The first link is related to a bug report that marks the unreliability of .IsLoaded, with a follow-up that it hasn't been fixed yet.

    To give you a potential solution is, to instead of using a callback function, get the assets from the queue and check it's status intermittently, like so:

    local retryLimit = 12
    local retryCount = 0
    repeat task.wait(2) retryCount+= 1 until ContentProvider:GetAssetFetchStatus(DayTheme) == Enum.AssetFetchStatus.Success or retryCount > retryLimit