Hello, I’m not sure if this is the right category for this kind of issue, I’m still a bit new to this.
I have a server script that generates Parts with SurfaceGuis and ImageLabels with a specific texture inside it, and after all the parts I want got generated, I have a function that checks the .IsLoaded property of each ImageLabels and waits until they are all true. For my game to “work” I need all of these image to be loaded before doing anything else.
The waiting function in question if it can help:
function WaitForFrames(folder)
local loaded = true
for _, frame in ipairs(folder:GetChildren()) do
if frame.SurfaceGui.ImageLabel.IsLoaded == false then
print(frame, "isn't loaded")
loaded = false
else
frame.Position = TV.FramesPos.Value
end
end
if loaded then
return
else
task.wait()
WaitForFrames(folder)
end
end
The issue I have is that the images property is only true on the client, and stays false on the server now matter how long I wait, but when I switch to Server View in studio, they are loaded instantly. Also if I move away the “Server camera” the images never loads.
(The images are white on purpose, They are moved in front of the screen when the “Loading function” returns, and as you can see I have to go to server view for this function to return, also I forgot to include this in the video but the images really are loaded on the client)
To my mind it’s an expected “studio Behavior” but will it be the same when I publish the game ?
Also is this the right way to do it ? What I want is for all the player around the part to be able to see the images, so they need to be loaded for those people at least, and I though that waiting for them to load on server was the best solution.
Is there a way to force the server to load them ? I don’t have a very clear idea of how replication works either, even if I understand the idea of it.
Any kind of help will be appreciated, even docs to look through or existing post I may have missed.
The server doesn’t actually see anything so it doesn’t load any images
what you are looking for is probably ContentProvider | Documentation - Roblox Creator Hub
just preload the images on each client in the start of the game
to clarify the server doesn’t load any meshes or images, it only runs code and each client loads their own mesh or image separately from everyone else
1 Like
Hey, I’d preload them on each client:
-- LocalScript in StarterPlayerScripts
local ContentProvider = game:GetService("ContentProvider")
local folder = workspace:WaitForChild("YourFolderName")
ContentProvider:PreloadAsync(folder:GetDescendants())
1 Like
But I think they are already loaded on the client. Plus I’m working with a server script, which checks if the images are loaded.
What I want is that the images are loaded for everyone, and when this is achieved, the server scripts do stuff like playing audio and making the images in front of the screen 1 by 1.
Do you recommend that I make this whole process client sided instead of server sided ?
I’m trying to think if this would be possible in the context of my game.
The image system that I have is dynamic, what I mean by that is that they will be many (many) images, and I’m planning to load only the needed one. In the video you can see me play a tape, in that case only the images in relation with the tape are being created and loaded(or at least that’s what I’m trying to achieve).
Because of that I don’t think ( I might be wrong) loading everything at the beginning will help. But maybe I can ask every client close to load the images through a remote and when they are done I can do the rest of the stuff on the server.
I’ll try that, and thanks for the clarification about Server side asset !
When an image is loaded it never unloads so it will definitely help, but are you sure whatever you are doing needs that many images and theres no other way to do it
1 Like
Well there are other way but it’ll cost some robux ^^. I didn’t know that, maybe I’ll try it out, thanks for the help.
Edit: Does loading many assets like ImageLabel will slow down the game for client ?
I don’t think ImageLabel.isLoaded works on the server because they are only rendered on the client. If you want to be 100% certain that all clients have loaded the ImageLabels I’d do it like this:
1: Create a RemoteFunction inside ReplicatedStorage called “LoadImageLabels”.
2: Create a LocalScript inside StarterPlayerService that loads the ImageLabels with Content Provider upon receiving the RemoteFunction, then they return true.
3: On the server, loop through all Players and use RemoteFunction:InvokeClient(Player) and wait for a response. If you want all players to load them at once I’d spawn a task per player.
Try one of these (Server):
-- Load each client in a row
local RemoteFunction = game.ReplicatedStorage:WaitForChild("LoadImageLabels")
local function loadImageLabels()
for _, Player in pairs(game.Players:GetPlayers()) do
local status = RemoteFunction:InvokeClient(Player)
end
end
-- Load each client at once
local RemoteFunction = game.ReplicatedStorage:WaitForChild("LoadImageLabels")
local function loadImageLabels()
local stats = {}
for _, Player in pairs(game.Players:GetPlayers()) do
stats[Player] = false
task.spawn(function()
stats[Player] = RemoteFunction:InvokeClient(Player)
end)
end
local function checkStats(t)
for k, v in pairs(t) do
if v == false then
return false
end
end
return true
end
repeat wait(0.1) until checkStats(stats) end
end
Here on the client:
local RemoteFunction = game.ReplicatedStorage:WaitForChild("LoadImageLabels")
RemoteFunction.OnClientInvoke = function()
local ContentProvider = game:GetService("ContentProvider")
local folder = workspace:WaitForChild("YourFolderName")
ContentProvider:PreloadAsync(folder:GetDescendants())
return true
end
(All are Pseudo code; let me know if they work.)
I hope this helps!
1 Like
Thanks you, I have done something similar on my side even before reading your reply, but now I’m having another issue, the PreloadAsync() doesn’t seam to load correctly the images.
I use a remote function with both ways connection but maybe a remote function is more appropriate, I never used those successfully. Here is the client script:
local ContentProvider = game:GetService("ContentProvider")
local event = game.ReplicatedStorage.Events:WaitForChild("LoadFrames") ::RemoteEvent
--Folder contains the parts and images
event.OnClientEvent:Connect(function(Folder)
ContentProvider:PreloadAsync(Folder:GetDescendants())
print("Done loading")
for _, image in ipairs(Folder:GetDescendants()) do
if image:IsA("ImageLabel") then
print(image.IsLoaded)
end
end
event:FireServer()
end)
And this is what happens in game:
even after the PreloadAsync I go through the images and none of them are loaded, I’m I using it wrong ? Also isn’t it supposed to Yield ?
Here is the server script if it can help:
local playerinrange = GetNearPlayer() --Table
local timeOut = 0
--Load frames on clients
for _, plr in ipairs(playerinrange) do
LoadFrames:FireClient(plr, PhysicalFrameFolder)
end
local connection = LoadFrames.OnServerEvent:Connect(function(player: Player)
if table.find(playerinrange, player) then
--Removes the players who had loaded from the table
table.remove(playerinrange, table.find(playerinrange, player))
print(player, "has loaded")
end
end)
while #playerinrange ~= 0 and timeOut < 50 do
--Continues when table is empty (all player have loaded) or when timeOut is exided
task.wait(.1)
timeOut += 1
end
connection:Disconnect()