Divorce the loading of StarterGui from CharacterAdded

As a Roblox developer, it is currently too hard to have UI in a game with character loading disabled, because the contents of StarterGui are restricted to loading when a character spawns.

If Roblox is able to address this issue, it would improve my development experience because it would allow me to more easily create UI without workarounds.


(Take the stuff below with a grain of salt, primarily just focus on the stuff above since this stuff is more separate from the problem and feature request)

The definite biggest use case is for menus or loadout screens (e.g. clicking a Play button to play, or something like Phantom Forces’ or Arsenals’ loadouts)

Common workarounds and their problems
  • An uncommon but somewhat proper workaround is to insert UI by a script, but this means reimplementing Roblox features like ResetOnSpawn yourself, which is problematic even though it’s low difficulty because it offers more opportunity to race conditions and bugs, and makes it more difficult to take advantage of Roblox features that are added.

  • An older and still very common workaround is to allow the character to spawn, but first place them in a loading zone or box, which is problematic because it requires making sure it can’t interfere with gameplay or spawning (or giving cheaters tinder for their fire)

    • I’ve chosen to strikethrough the below because it’s misleading – Examples of games which use spawn boxes are not examples of games which use this as their workaround, and these aren’t the types of games or projects this feature request pertains to.
    • Side-note: There are an enormous number of games both modern and old which do (or did) this for their menus. Arsenal and Phantom forces are both among them afaik, as well as a lot of FPS games like BIG Paintball, and both have experienced their fair share of glitches and exploits around it
'Ideal' case (not really meant to be a proposal)

This would ideally be solved with something which isn’t too complicated or hidden, and adds more fine-tuned control to when UI loads from StarterGui.

This could be a good opportunity to allow for developers to have UI which loads the first possible instant, just like the old and deprecated teleport UI mechanics which were very good at making a seamless transition (no default skybox popping up with slow internet)

36 Likes

The first workaround of just cloning the contents of StarterGui is a perfectly fine solution that gives developers the most control. It can be done on both the client and server, the developer has complete control over when and what gets cloned and it works just the same as if you had a character loaded. If you’re making a whole custom character spawning system then it wouldn’t be too hard to also make ResetOnSpawn behaviour.

In Arsenal we have CharacterAutoLoads as false and call LoadCharacter once due to how often players would completely reload their character on death and the performance hits that would come with it. Instead we use an alternative “health” value and when that reaches zero we move the character to a “spawn box”, play the kill effect where they were last standing and then after the death delay we reset their player values and spawn them back into the map.

This solution works well for us and there haven’t been any noticeable issues or exploits with it that I’m aware of as of recent. As long as you correctly handle player states and check the right things it shouldn’t present any issues.


Besides all that I do agree it’d be nice to have the engine automatically clone over the contents of PlayerGui even without a character loaded, but this could cause issues with games that already do this themselves. It’d probably need to be a new property in StarterGui that defaults to false.

10 Likes

You should never use StarterGui, the best thing is to clone it from ReplicatedStorage locally as it’s useless and actually bad for your server to have access. This can decrease RAM usage on the server.

5 Likes

The question though is how does the engine or the developer determine when to display Gui? If not by the character spawning, then there needs to be a trigger for that clone operation. I’d see the likely answer being a new API method but as an abstraction to just cloning the Guis sounds like API bloat.

In the case of an abstraction API, you’d still have to write some of the systems you highlighted as problematic for the workarounds (e.g. distributing every respawn while the backend determines which ones need to be cloned) because then you’d have control over when those Guis replicate - no different than what you can do now with just Clone.

As mentioned above too, there’s been a few developers who’ve known or found out that StarterGui is not sound even if you do have character loading enabled. As the server is the entity that replicates the contents of StarterGui to players, the server will track references for (n+1)x copies of every Gui (where n is number of players, x is the number of Guis and the +1 accounts for the original copies in StarterGui). If you’re developing for performance and low memory consumption even by a little bit, you don’t want to use StarterGui.

2 Likes

If you shouldn’t ever use StarterGui for UI like you suggest, then there is something wrong and there absolutely should be feature requests targeting it. StarterGui is intended for UI, and, if I shouldn’t use the feature intended solely for UI for UI, then why even have that feature at all, why not just deprecate it?

In this case, improve not remove imo.

Also, I haven’t really heard of StarterGui using more RAM on the server (I can imagine the reason being weird and unecessary), but that’s way more so a reason to create a bug report so the issue can be eliminated, not a reason to say a feature is bad or shouldn’t be used

This is always a valid solution for sure, I definitely don’t deny that. But, I don’t think that it’s objectively a good workaround, it depends heavily on the situation and what you want to do.

What I want to do is to be able to get a solid foundation for a game without caring about performance or memory. I don’t want to spend time on implementing something analogous to something that already exists, at least, until I decide it’s worth it to do that. The thing is, this is still more than compatible with just using StarterGui initially so I can make my concept and keep my work space as low clutter as possible.

Yeah, it’s not really that difficult to replicate pretty much any UI spawning behaviour I know of, but, I was trying to point out that it’s unnecessary that a developer should have to reimplement every feature for controlling how a UI spawns. If Roblox adds more features in the future, I can’t utilize it without reimplementing it.

The rest of what you said there in response to my comments on spawn boxes makes a lot of sense to me, and, I like your implementation. But, it’s also a relatively large task to implement something like that for not particularly much benefit.

Yeah, I considered a lot of cases and problems before posting because this is a much more complex problem than it looks like at first. Really my conclusion was that there is no “zero-effort” solution like tweaking existing behaviour.

You can’t load UI early normally because it can break scripts present inside of the UI. You also can’t load UI automatically just because CharacterAutoLoads is off for the same reason, because normally the UI won’t load without a character, and CharacterAutoLoads being off doesn’t tell the engine that scripts inside of UI won’t require a character, so, games designed with that could break.

This leaves only one path which is to add new functionality to control the behaviour. Plus, it would imply being able to load UI at any time.

I’m not really sure I understand. The creation/insertion of UI doesn’t need any trigger to work, you can “reset” the UI at any time as many times as you want, or not at all. You can have multiple triggers, or none, etc.

What I’m asking for is a way to immediately load UI regardless of if the character spawned, ResetOnSpawn behaviour doesn’t need to work any differently.

The backend doesn’t need to determine what UIs need to be cloned at all, and in fact doesn’t do this in any form, that info exists already, just based on the value of ResetOnSpawn.

In PlayerGui, a truthy value of ResetOnSpawn results in the UI being deleted.
In StarterGui, a truthy value of ResetOnSpawn results in the UI being created every CharacterAdded (as opposed to only the first one with ResetOnSpawn falsey)

There’s no tracking at all.

If ResetOnSpawn is off with a UI present in StarterGui, it gets inserted after a player joins, and their character loads for the first time, but never again.

This is pretty easy to verify:

  1. Just hit play in a new baseplate
  2. Switch to server view, then insert a ScreenGui with a TextLabel, and disable its ResetOnSpawn property.
  3. If you reset, you’ll notice that the engine doesn’t copy the UI at all, because the UI would already be present.
  4. Then switch back to the server view and enable ResetOnSpawn.
  5. Reset, the UI will suddenly get inserted after you reset your character.
  6. If you then remove it from StarterGui and reset it will be removed.

You can also test that the backend doesn’t care if a UI already exists:

  1. In a new baseplate, insert a UI with ResetOnSpawn disabled and hit play. The UI will be visible.
  2. Switch to the server view, and in StarterGui, enable its ResetOnSpawn.
  3. Reset your character. You will notice that, despite being the exact same UI instance, the engine does not remove the old one, and instead creates a whole new clone, resulting in two of the UIs

In other words, the server literally has no concept of where a UI came from, and doesn’t need to decide if a UI was already cloned.

9 Likes

A bit of a pedantic response. Tends to happen when replying to the verbatim wording rather than the spirit of or the whole reply. I didn’t imply any need to change any existing behaviours, the question I rolled around is how the engine or the developer are going to determine when to display the Gui. Right now that’s CharacterAdded but you want a way to get Guis into PlayerGui without it.

At some point, your code or the engine are going to need to understand and process your request to insert Guis, which is what I mean by “trigger”… so what you’re saying is a bit contradictory in “creation/insertion doesn’t need any trigger to work” but you want to “have multiple or none”. I think I understand what you’re saying though – you’re saying we shouldn’t need a point to load Guis and instead be able to determine that on your own with something that’s included in the engine. That’s what I meant, don’t focus too much on the word choice.

The whole technical repro is pedantry. I didn’t mention tracking, I mentioned determining. Right now I’m walking into this feature request thinking you want a way to clone Guis to PlayerGui so natural respawn logic wouldn’t really apply here? There would need to be determination of which Guis to clone by something.

My thoughts when I wrote that second paragraph were: how is it going to know which ones it should clone? Is the API only going to acknowledge ResetOnSpawn = true Guis? How are you going to initially populate ResetOnSpawn = false Guis to PlayerGui? If the character doesn’t spawn PlayerGui won’t be populated so will it just blanket add all Guis regardless? In practice it doesn’t make much sense to say that there would be no determination but the question is how.

I get that for ResetOnSpawn false, the first spawn will add the Gui and then the server doesn’t care afterward until ResetOnSpawn is changed; while for true it’ll add it back every time. Now, going back to how it’s logically sound this feature request would be implemented via method call, how is ResetOnSpawn going to be factored in here? Replicate that behaviour internally - first call of the method is like the first spawn and subsequent calls are like subsequent respawns?

There would be a difference if you were asking for the ability to reload UIs without waiting for the character to respawn instead of asking for a way to display UIs without a character since the latter is already a thing. Guis displaying is not tied to characters besides populating PlayerGui via respawn. This much isn’t pedantry and changes the meaning of what’s being asked for here.

I can see a significantly stronger case in being able to completely reload StarterGui without CharacterAdded but I didn’t get that impression from your original feature request and it looked like you just wanted the ability to clone – there’s some disconnect in the OP and your replies. There’s no need to abstract cloning and you should just write it yourself. Divorcing reloads from CharacterAdded is a sound feature request.

2 Likes

The reason is that the server would have access to the UI which is already an extremely heavy resource. StarterGui is meant for new developers and the proper way to handle UIs are through cloning it from ReplicatedStorage or any other place the client can access.

1 Like

Thanks, yeah, I overreacted to your reply and other people’s, and I apologize for that, I should be more careful in how I respond, and I shouldn’t have responded how I did. I directed a lot of general frustration at you that didn’t come from you, I want to have a more productive convo.

I think this comes from me just fundamentally misunderstanding what you were saying, and just being giant jerk man in how I worded my response.

To give a better idea on my feature request, what I’m asking for is specifically just simply any kind of better control over how and when StarterGui in particular inserts its UI, so that StarterGui can be used legitimately for any use case you might have, not just one where you always have a character spawn right away. This tie in with characters I’ve found exists on a lot of stuff, and this is super bad because what if you don’t want characters at all? Or, what if you just want to avoid replication exploits altogether? It makes characters and UI “stick together” because it’s naturally a lot more difficult to avoid.

I think that StarterGui is almost useless for anything I want to make right now because it forces me to do all this stuff with characters that I don’t want, when StarterGui should be perfectly acceptable for any sort of UI stuff. In this case, natural respawn logic naturally still applies, since its still StarterGui (otherwise it defeats the purpose of StarterGui, e.g. if you go for an alternate solution like direct UI insertion, or if you come up with a compromise that excludes respawn logic)

Really, in the end, I don’t care what the end solution is, I split my example solutions out on purpose because they’re separate, as long as it solves the StarterGui problems.

This is probably what I’d expect, I was just expecting a way to call upon the existing trigger in that part of the discussion, which, would be pretty low effort to implement and would kind of provide more control. Even though I listed it, I actually don’t really like a scripting API all that much since it sort of doesn’t fully solve the problem, it would be an easy nice-to-have plus a proper solution, and it falls into the same area enough that it fits nicely with other features or changes I think.

I think my title and request are worded too vaguely, because really the problem isn’t just the ability to display UI with no character existing, it’s the ability to do that more easily, and in a way that makes sense. More specifically, with StarterGui in particular, since as a feature, StarterGui is supposed to offer, well, all the UI stuff. I don’t want to be required to write my own code to work around overhead that, in an alternate universe where it didn’t exist, would have less downsides (UI being tied to character spawning)

Yes this is actually exactly what I was thinking originally :flushed:
I agree, I think I definitely abstracted it too much, I have some edits in mind and will make them shortly.

2 Likes

Edit/Correction:
I had talked directly with @SharpSerious in DMs, and I was missing the point of what was being said yet again. :sunglasses: The point is just that because the UIs are server owned with StarterGui vs just being created locally, they take up server memory, since each player has those UIs. This isn’t specifically related to StarterGui, but it is an important detail, since you can avoid any extra memory usage on the server by just not creating UIs server-sided.

(Read above first)

I don’t really agree, I think this logic is a little unreasonable, no offense intended.

There’s no reason StarterGui should have to be restricted to new developers, it’s a perfectly sound concept, but it has problems, which is the reason why I made this post. Having a central location for UI is no different than having a central location for scripts, like ServerScriptService, or StarterPlayerScripts.

I speculate that your claims that StarterGui/UI are a heavy resource are speculative (funy hypocritical joke)… Could you link to a post (or maybe create one somewhere if it doesn’t exist) that goes into more detail on both why and how StarterGui is currently a heavy resource, so people here can better understand the issue?

To me, there is no logical reason for why StarterGui could have any cost, it just doesn’t make any sense based on my current knowledge of the engine. I can’t emphasize this enough, you should make some detailed bug report(s), or resource(s), the concept is not bad just because the implementation is, and a bad implementation doesn’t always mean it’s bad to use it when there are tradeoffs you would like.

I’m resistant to be receptive to some of what you’re saying, partly because I don’t think it’s really relevant to my feature request, and partly because I don’t think it’s accurate just from what I know, I need more information.

That’s really anything I have to say, I think that any more discussion about whether or not StarterGui is reasonable to use should probably go in a different place. I’m happy to discuss more in PMs or something, but, I don’t think I should continue to reply to discussion about this further.

3 Likes

The workaround I’ve been using is that on the server when a player joins it creates an empty model and assigns it as the player’s character just so the GUI will load. This results in a lot of Infinite yield possible on character:WaitForChild("Humanoid") warnings in the log though : /

This feature would make my life so much easier and my projects so much less messy.

1 Like