How to create client-side handler system?

My original approach on a client-side handler system was to keep all client scripts as descendants of ReplicatedStorage, and this WAS working for me, up until I realised that whenever the player reset, all variables that referenced perishable assets like UI and character assets would obviously continue to incorrectly reference their old versions after the new character and UI had loaded.


My first guess at a solution was that I may just need to go through every single ModuleScript and add a method to refresh every variable necessary so that it correctly references the new assets, but this to me seemed too tedious to be the true best solution for my issue;

local MyScreenGui = PlayerGui.YourScreenGui
-- or could just be set to nil

function module.CharacterAdded()
	MyScreenGui = PlayerGui.YourScreenGui
end

Instead, I found the original video that recommended the handler architecture made by crusherfire which did actually specify that scripts who handle perishable assets should in fact be placed into StarterCharacterScripts so that they restart entirely alongside the new assets, however I seem to be referencing these ModuleScripts that are initially parented to StarterCharacterScripts incorrectly; I assumed that you were supposed to reference them via the character, where they are during runtime, however I get a “unknown require” warning when I do it this way. Are you really supposed to retrieve ModuleScripts that are in the character at runtime via StarterCharacterScripts instead…?

-- MyModuleScript starts within StarterCharacterScripts;
-- I would assume to access it you would do this? v
local MyModule = require(Character:FindFirstChild("MyModuleScript")

-- and yet doing this in the code editor raises an error
-- + shows no autofill support

-- On the other hand, this does seem to work,
local AnotherModule = require(StarterCharacterScripts:FindFirstChild("AnotherModuleScript")
-- but its parent is still obviously StarterCharacterScripts,
-- and its too late for me to test if this works by myself today

Either way, I believe I’ve been making too many assumptions about what I should and shouldn’t be doing so I thought it might be best just to ask the community for the common practice when trying to create a handler system on the client. (The reason I specify this is because I’ve been thinking about this like my server code, which has been working entirely correctly but obviously stops working if you dont account for the assets within variables getting replaced during runtime)

1 Like

Bumping, I hate how competitive this category is for more complex questions… If you read over this post and got confused about anything that discouraged you from responding please lmk

Try doing a :WaitForChild() instead of FindFirstChild(). It’s likely that the script hasn’t been copied over yet before the code trying to require it runs.

I dont believe you understood what I said but I did use WaitForChild too and it made no difference: trying to retrieve the ModuleScripts replicated to the Character doesnt show autofill support which makes me believe I’m doing it incorrectly and should be retrieving the assets from somewhere else…? Still not sure where though.

Roblox is a little weird regarding auto-filling methods from a module script.
It requires you to have a direct reference to a module script with 100% certainty that it exists there.

So, you can’t do Container:FindFirstChild(ModuleScript) and expect autofill methods.

A potential approach would be simply requiring the module as such local Module = require(script.Parent.ModuleScript) (Assuming your LocalScript is under StarterCharacterScripts)

This is a direct reference to the module, and Roblox will provide autocompletion. At runtime, script.Parent is the character so you are referencing it properly.

This is technically a solution and would work however does have one flaw I immediately recognised; the reason I would prefer to reference scripts from the character and then working down through descendants is because starting from the physical location of the script means that navigating through folders becomes much more difficult when you have to go up through ancestors and then back down through descendants, aswell as being incorrect whenever you move the script to different parents…

Is this really the only way to reference other scripts replicated from StarterCharacterScripts?

Well, Character is just script.parent, no? So it is still referencing the character.
It’s no different than this:

local Character = script.parent
local Module = require(Character.ModuleScript)

yeah but not all my scripts are siblings, I have folders for organisation and scripts wont always be x amount of parents away from referencing the character

Well, as far as autocompletion goes you need some sort of direct reference.
How is Character defined in your case?

local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

I’m using autocomplete as “proof” that what I’m doing is probably the incorrect method, it isn’t actually the issue, just a consequence of the issue I’m dealing with.

The issue is whether you are properly referencing the module scripts.

The answer is Yes, you are. You are properly referencing them at runtime, and your variables will be “reset” alongside the module scripts.

So, as far as your concerns are, you don’t seem to be doing anything incorrectly. As far as convenience goes, I do recommend having a direct reference to your module script(s).

It’s better to define Character as script.Parent in StarterCharacterScripts, because it’s more direct, and CharacterAdded will never fire in a script inside of StarterCharacterScripts because the character is created before the script’s existence.

You don’t need this if you have ResetOnSpawn set on false btw :heart::heart::heart::heart:
Also you don’t need a static scope for a GuiObject either unless it’s for connections.
Also Backpack resets too on respawn.

I do understand that logistically simply referencing them from Player.Character will work, however what urks me is that I will need to use script.Parent instead on a case-by-case basis to reference to the same script as opposed to being able to simply reference an ancestral service/group like ReplicatedStorage/the character, to keep autofill support.

I’ve already stated that its likely none of my scripts will be parented directly to StarterCharacterScripts, instead being organised into multiple folders as they are now.

This code is simply the current method I was using to access the character, but I’d like to mention that the line you were talking about would still work because, like you said, Player.Character will always successfully return the character and so would never need to continue on to the CharacterAdded connection.


I think for now what I’ll try is keeping all my code where they are within ReplicatedStorage, however encapsulate all my code into a Refresh method so that variables can refresh accordingly whenever a new character is added.

wdym…? My ScreenGui’s already have this enabled?

Could you explain what you meant by static scope? I’m not sure what you meant here.


sorry I didn’t reply immediately after I responded to the first reply, I went to doublecheck after reading the second line but I was correct when I said the variables pointing to GuiObjects (like in the line you quoted) will still point to the old, destroyed UI after they reset when the character respawns.

Then you don’t reset its variable everytime the player respawns, it will stay the same!

Yes, it will reference the same GUI even after it has been reset and discarded right?

Maybe we’re miscommunicating right now; the script I’m currently running is in ReplicatedStorage, so it will not refresh and reference the right GUI even after the character and GUI resets, which is my issue.

mb on the later response compared to my previous response times, I was reconstructing my code so didnt have time to properly read over and respond to your reply, although I do believe you misunderstood me; I meant autofill as in suggestions on the actual contents of the module, rather than simply the ModuleScript class.

As for the second quote, I will admit I did phrase that incorrectly as I think I meant to say that it was raising a warning in the code editor of an “unknown require” which is what lead me to believe that the code editor couldn’t interpret that the scripts would eventually end up in the character.

In the end I found this approach to be the easiest while keeping autofill support and so I ended up doing it this way and got everything working again, this time even after resetting! (i hope so, its late and i just quickly tested things but they seemed to work now :sweat_smile:) I’ll be leaving your first reply suggesting this method as the solution. thanks!! :+1::+1:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.