Deferred Engine Events

That’s the whole point, the two “obvious solutions” are not an option because of how Roblox works.

You would end up with a constantly expanding pile of spaghetti code that becomes harder to maintain every update.

The engine is an integral part of the whole platform. Any legacy engines would have to be constantly maintained as well so that they keep working. It would be much, MUCH harder and more expensive to version the Roblox engine compared to something like the Unity Engine, which in itself is not a platform but can be used to make games - all of which are standalone products that do not need to cooperate.

Moreover, players would be forced to download multiple versions of the engine to play various games, increasing disk space usage and time spent downloading. This gets even more complicated when we take mobile and console devices into consideration where the update mechanisms are very different. Plus, mobile users are much more sensitive to download sizes and they’re much less likely to download an app if it’s 5 GB in size.

4 Likes

I don’t really care about the implementation details, I just care about Roblox finding a solution. A lack of backwards compatibility is only going to become more and more of an issue over time as the catalog of high-quality legacy games grows. Adopting a defeatist attitude of “it’s too hard/impossible so they should just break old games” won’t help anything.

6 Likes

Most of the reason this is being changed is for cases like this:

Player.CharacterAdded:Connect(function(Character)
	Character:PivotTo(CFrame.new(13, 32, 51))
end)

On paper this looks like it should work, but the problem is with Immediate SignalBehavior the callback for CharactedAdded gets ran immediately after the character is added, which unfortunately means the character is most likely going to be positioned back to spawn after this runs.

Deferred SignalBehavior fixes this by running the callback after the engine’s schedular has resumed (Called the Resumption Cycle), meaning Character:PivotTo will work as intended.

Before, people would probably have tried to mitigate this with yielding an arbitrary amount of time or (more appropriately) wrapped it with task.defer.


A similar scenario would be if you’re trying to reparent/destroy something after it got removed, which would throw an error.

workspace.ChildAdded:Connect(function(Child)
	-- Something unexpectedly tried to set the parent of Child to NULL
	Child:Destroy()
end)

These error messages require case-by-case sanity checks inside the C code or else the client might crash. With this change these edge-cases would become non-existent and engineers would no longer have to worry about taking care of them.

That’s why this change is required, even if it breaks backwards-compatibility. While it might be annoying for us to fix old code, it’s going to make writing new code much easier for both developers and engineers, making things more forward-compatibility in the long run.

28 Likes

This actually is a bit concerning considering I sometimes have to clean up things at object removal.
I use module scripts and metatables to implement object-oriented designs and re-usable code, some of which might have to clean up or delete references to an object so there are no memory leaks.

3 Likes

You could use RBXScriptSignal:Wait instead, which would act the same way as Immediate.

task.spawn(function()
	script.Destroying:Wait()
	part:Destroy()
end)

Although this definitely is a weak point with the implementation and I’m not entirely sure how one would fix it in a streamlined manner. Maybe make an exception for some instances?

6 Likes

Being extremely ignorant won’t help anything here either. I just pointed out why your proposed “obvious solutions” would not work in this case.

4 Likes

You should not be writing code like this anyway. Do not rely on multiple scripts.

1 Like

I still do think that the timeline to switch the default behaviour is incredibly ambitious knowing how long we’ve been used to, expecting and sometimes (scarily) reliant on the current signal behaviour. Besides that though, I really don’t have many issues with this update. I really like it.

Deferred signal behaviour was one of the more difficult technical updates on Roblox for me to grasp in terms of intent, how it works and how to best apply it. I’ve gotten better at using it now since being completely clueless in the past and deferring even in immediate has been pretty helpful.

I still have a ways to go for some of my projects to make sure they are fully developed with deferred events in mind (especially ones with huge technical debt) so the opt-out does help for those use cases at the very least. I hope I’ll be able to reach a point of familiarity where I don’t need to opt-out.

I didn’t even know that deferred was able to improve the security of scripts, that’s incredibly fancy actually. Also pretty pumped about the performance gains. My main hope is that deferred will give Roblox the opportunity they need to fix long standing issues with certain pipelines (ESPECIALLY avatar loading events ordering, characters not being loaded atomically is a huge pain).

13 Likes

Deferred catches wrong doings a lot better than immediate :slight_smile:

This would be a bit of a fool’s errand. The issue being that there’s a very broad spectrum of backwards-compatibility, with no clear dividing line between “backwards compatible” vs not.

In fact, the majority of “backwards compatible” changes we make are technically not backwards compatible to a handful of unlucky developers out there who just happened to depend on a very specific confluence of behaviors which no longer line up the same way.

So, you wouldn’t be able to rely on such a listing of breaking changes even if we published it: Either it would have to list only major breaking changes, which means you can’t trust it to always list the changes that matter to you, or it would have to list so many changes that it wouldn’t be worth reading.

8 Likes

Sure, and even bug fixes break code, but I think even listing major changes that could result in non-obvious breakage (like this or the coroutine identity change, maybe contextually filtered for functionality a game uses, to the extent that’s possible) would be preferable.

The current reality is that there’s not really any easy way to know what changes would need to be made to get a game from 2014 working, unless you keep up with changes continuously.

2 Likes

For Server->Server or Client->Client use

For Server to Client or Client to Server use remoteevents.

1 Like

Does this update affect thread spawning through task.spawn/coroutine.resume etc. or is it purely for RBXScriptSignals

1 Like

@RuizuKun_Dev @MysteriousVagabond any experiences that have SignalBehavior set to Deferred on April 12th will automatically start using the new behavior.

1 Like

We will look into this. Thanks for the report.

2 Likes

If you have any feedback on debugging with deferred events enabled then we are interested in hearing it. There are some changes we have made since the initial release that should make debugging easier but if there are still issues you’re running into then that would be great feedback for us.

Enabling this feature changes the timing of when event handlers run in the engine. Unless you’re writing code that expects handlers to run at a specific time then it won’t really matter which behavior you select. If you can opt-in early then I would encourage it as there are a number of benefits mentioned in the original post to doing so.

We are also working on providing more documentation for deferred events. Expect that to be available on our documentation site in the coming weeks.

1 Like

Now I’ve been thinking.
Since this update might break really old games that are no longer updated.

Wouldn’t it be more useful to only automatically apply it to games made beyond a certain date rather than all games that have the variable in workspace set to “default”?

I’ve noticed some Roblox updates are just automatically enabled by default once released.
But wouldn’t it be more friendly to older games to basically…

if game.CreationDate < 2019 then DontUpdate() end

(Psuedo code. lol)

Is there a reason updates are automatically enabled for all games? I’m genuinely curious.

2 Likes

note: Not tryna make an off-topic/unrelated argument, just spitting out some informal thoughts

Isn’t that the reality of being a programmer or just any other profession? That things will always be changing and updating all around us and that we gotta keep up w it? Breaking and non-breaking changes included (because that’s what it takes for stuff to progress, no?)

If someone chooses to take a really long break (like 5 years away) from Roblox but has a couple games, they’re indirectly choosing to no longer maintain them- Because who else can?.. unless they leave the game in the hands of someone else, their studio, or its community (uncopylocking). In all that time, parts of the API could get deprecated and replaced, some major oversights could be mended, and so on

I do kind of understand the other side though- if someone just walks away from Roblox for like a reasonable amount of time, their games shouldn’t just fall apart and have to be completely reprogrammed. but if we had that same mindset for FE, the engine couldn’t be where its at rn. (I’m saying this in spite of the exploiter situation on Roblox still not being the best).

It’s like choosing between holding onto the past & thus limiting future progress or holding a softer grip on the past to pave the way for future progress

6 Likes

I don’t understand since my english isn’t good,
What do we need to change before roblox launch the update?