Sometimes at one session ModuleScript or other thing like BindableEvent isn't instantly replicated

Like the title said, sometimes when i start a playtest session, one modulescripts or bindableevent can’t be found by scripts because it ‘isn’t loaded’ when the script referencing it, thus “Not found”, making the whole scripts error.

I heard from experts and some guy on the forum and fully believed it that “Replication is synchronious” and “Too much :WaitForChild() is a bad practice”. But because of this issue, i can’t help but always band-aid it with WaitForChild() and honestly i, too, tired of having to WaitForChild() everything.

What should i do to prevent this so i can consistenly reference it without “One-in-a-time” error?

3 Likes

Just use WaitForChild for anything clients wait to be replicated to them. If you want to avoid WaitForChild then avoid using it for server → server and client → client things when you know the resources load together.

Can you elaborate on the second sentence about server > server and client > client thing? Do you mean like RemoteEvent?

Sorry i wasn’t being clear. But its mostly happening to local scripts which they reference to local sibling module in PlayerScript. I also put some BindableEvent in sibling at PlayerScript. I have no issue referencing thing for server side.

If you load on the server-side, the server loads quickly so you can find it right away. However, it takes time for the client to be copied from the server to the client, and if the LocalScript is loaded first, it may not be found and an error may occur. Therefore, WaitForChild() can be a good method, but if you don’t want it, you can have it run on the server or wait for it to be loaded like task.wait() or game.Loaded:Wait() method, but I don’t recommend it.

I never use WaitForChild to reference GUIs or require modules because I don’t have to. I wait for the client to load before copying UI and all modules from ReplicatedStorage. In my game of 100+ modules and 13,000+ lines of code I only use WaitForChild three times. I have a local script parented under StarterGui which runs when the player joins and every time they reset.

Example code
-- This local script is parented under StarterGui which automatically gets cloned into PlayerGui where it actually runs
if not game:IsLoaded() then game.Loaded:Wait() end

-- Since all GUIs are now loaded, copy all of the user interface into PlayerGui
local cont = game.ReplicatedStorage.UiContainer:Clone()
cont.Parent = script.Parent

-- Delete previous client code (this is needed after the player resets)
local p = game.Players.LocalPlayer
if p.PlayerScripts:FindFirstChild("ClientCore") then
	p.PlayerScripts.ClientCore:Destroy()
end

-- Copy all modules
local core = game.ReplicatedStorage.ClientCodebase.ClientCore:Clone()
core.Parent = p.PlayerScripts

-- Require modules. Since all UI and modules have loaded, none of these modules need to use WaitForChild.
local modules = {}
for _, i in ipairs(core:GetDescendants()) do
	if i:IsA("ModuleScript") then
		modules[i.Name] = require(i)
	end
end

This video goes more in depth (it also tells you how doing this can save a ton of server memory):

1 Like

I mean that WaitForChild is often not needed in cases where a server is looking for a server resource or a client is looking for a client resource if they happen to load at the same time and you know it(for example if those things happen to exists in folders prior of the game starting).

When you use instances in scripts I suggest disabling their streaming enabled properties(basically considering them important instances) instead of using WaitForChild on them.

I have no problem with referencing instance in script, since there’s never been an issue of not loading in early. Its generally just happen for module script and bindableEvent for some reason (Additional note is that they’re siblings, both under the PlayerScripts or StarterPlayerScripts