ContentProvider:PreloadAsync() not working?

Anyone know why after doing

ContentProvider:PreloadAsync(workspace.Map:GetDescendants())
LoadingScreen.Visible = false

I can still visually see that the map hasn’t loaded in?

2 Likes

That’s not what you need for a loading screen…
You’ll need more code.

Tutorial

1 Like

I was just showing the loading part, that’s actual loading screen is irrelevant I just want a way of telling when the map has fully loaded

ContentProvider just loads assets, not the actual map. If you need to do this, IIRC game.Loaded is the way to go here.

game.Loaded most certainly does not wait until the whole map has loaded in

Use the tutorial I provided but don’t use any of the UI bits.
Make sure it’s on the client and in ReplicatedFirst

That tutorial does not have anything to with loading the physical map. To be clear @Myron_RDS, the parts and such are just no loaded in?

I’m confused on what you mean.

My actual visual loading screen works fine, it’s just the length is determined by:
ContentProvider:PreloadAsync(workspace.Map:GetDescendants())
which yields until the map has loaded but the map hasn’t actually always fully loaded in even after using that.

Use :WaitForChild(“Map”), that might be the issue

It’s not that didn’t fix it it still doesn’t wait for the map to load in

Do you have StreamingEnabled turned on?

PreloadAsync is meant to load images, sounds, probably meshes as well

StreamingEnabled = false
It’s quite a small map (3000 parts)

are you using meshparts or the roblox parts?

If you are using the roblox parts, they are already stored inside the roblox files, so they don’t have to be loaded. It might be that the client is just not rendering it perhaps?

mainly meshparts
normal parts as well but mainly meshparts

Try loading each asset individually.

local assets = workspace:GetDescendants()
for i = 1, #assets do
    local asset = assets[i]
    ContentProvider:PreloadAsync({asset})
end
1 Like

The solution to this issue is more complicated than what the previous answers elude to, and has nothing to do with PreloadAsync except timing.

The map loads into the workspace on the server, then replicated to the client. After you load the assets on the client, you need to wait for a remote event on the client to pause execution until the server fires that event after the map is loaded. Then when the GUI is destroyed, the map appears to be fully loaded.

Server

-- ******** Services
local replicatedStorage = game:GetService("ReplicatedStorage")

-- ******** Local Variables
local eventFolder = replicatedStorage:FindFirstChild("Events")
local eventLoading = eventFolder:FindFirstChild("LoadCharacter")
local eventMapLoad = eventFolder:FindFirstChild("MapLoaded")
local mapLoaded = false

-- ******** Events

-- Called when the client has finished loading assets and is ready to load
-- the player's character model.
eventLoading.OnServerEvent:Connect(function(player)
	while mapLoaded == false do
		task.wait(0.1)
	end
	eventMapLoad:FireClient(player, mapLoaded)
	player:LoadCharacter()
end)

Client

-- ******** Services
local replicatedFirst = game:GetService("ReplicatedFirst")
local replicatedStorage = game:GetService("ReplicatedStorage")
local playerService = game:GetService("Players")

-- ******** Local Variables
local mapLoaded = false
local localPlayer = playerService.LocalPlayer
local playerGui = localPlayer:WaitForChild("PlayerGui")
local loadingScreen = replicatedFirst:WaitForChild("LoadingScreenGui")
local eventFolder = replicatedStorage:WaitForChild("Events")
local eventLoading = eventFolder:WaitForChild("LoadCharacter")
local eventMap = eventFolder:WaitForChild("MapLoaded")

-- ******** Events

-- Called when the server completes loading the game map.
replicatedStorage.MapLoaded:Connect(function(loaded)
	mapLoaded = loaded
end)


-- ******** Run

local clientGui = loadingScreen:Clone()
clientGui.Parent = playerGui
replicatedFirst:RemoveDefaultLoadingScreen()

-- Perform PreloadAsync

eventLoading:FireServer()
while mapLoaded == false do
	task.wait(0.1)
end
clientGui:Destroy()

Something like that should be what you need. When PreloadAsync has completed, it will send a request to the server indicating that it’s ready to proceed. On the server, the response is held until the mapLoaded variable is true. mapLoaded is set to true when the code that loads the map is done. When that happens, all the clients that have signaled that they are done loading assets are then responded to. When the clients receive the new value, they remove the loading screen Gui.

For clients that connect afterwards, they proceed immediately since the server has long completed the map loading. If there’s other conditions to check to see if the clients can be loaded, those can also be checked for too. You could probably use a remote function for this, but I prefer using remote events. If you’re using Parallel LUA, on the server, you can have the busy-wait loop run in parallel mode so as to free up the main thread, but the script has to be running under an actor for that to work.

I’m confused as to what’s setting mapLoaded to true on the server? Seems like it will wait infinitely.

1 Like

I probably should have made that more clear. The routine that’s loading the map does that. It may be better to make that a global variable with the _G property so no matter what script your map building routines are in, it can be accessed.

Are saying that the problem is that the client has loaded which is why the ContentProvider:PreloadAsync stopped yielding. But the server hasn’t fully loaded? I don’t understand because I thought it loads to the client being replicated from the server so how is it possible that the client has loaded in without the server having loaded in?