------------------
--[DECLARATIONS]--
------------------
----/[SERVICES]\----
local plrs = game:GetService("Players")
local repStore = game:GetService("ReplicatedStorage")
----/[REMOTES]\----
local charLoaded = repStore:WaitForChild("CharacterHasLoaded")
------------------
--[SCRIPT LOGIC]--
------------------
--A player has joined
plrs.PlayerAdded:Connect(function(plr)
print("PLAYER HAS BEEN ADDED, PLR:",plr)
--Fire charLoaded if the character of the player has loaded
plr.CharacterAppearanceLoaded:Connect(function(char)
print("Player's character has loaded! Player:",plr,",applying delay...")
wait(2)
print("Delay applyed! Firing event for ",plr)
--Fire event
charLoaded:InvokeClient(plr,char)
end)
end)
So, every time the player's character loads, it will fire a RemoteEvent to the player.
It works fine, though sometimes. I've been told by some of the players who played my game, that in random moments, this won't work.
I've been testing with these players, and I've noted that, in some cases, the print in Line 21 won't fire(which means that, CharacterAppearanceLoaded has not fired), when they reset or join the game, while I was using the in-game console.
The system I've made seem to work flawlessly for me, but not for some players.

2 comments
Depending on how important loading the character appearance is you could make it override the wait for appearance to load at some time (like 30 seconds)
You used InvokeClient, which is a YieldFunction of RemoteFunctions, not RemoteEvents.