Alright then let’s go a bit more on the basic level.
So let’s talk about task.spawn/defer/delay
, coroutine.create/wrap
and spawn/delay
functions. While all these functions behave differently, they all have one purpose in common: To run multiple parts of code seamlessly at the same time via using separate thread
objects. You might think of separate coroutines
/threads
(Whatever you want to call them.) as separate physical cores of processor (CPU on your computer.) doing tasks at the same time but that’s not exactly the case.
You see, while the Roblox engine uses actual multithreading for physics simulations, rendering, ect., the language and the language that the former language is based on that you write your code in for the game, Luau and vanilla Lua 5.1.4, always used “asymmetric coroutines” at the core, always has been. This means that all those thread
s actually runs on a single core on your CPU. What asymmetric coroutines does to mimic “multithreading” it that it switches between different thread
s very quickly by yielding the thread
it’s currently executing and unyielding another thread
and start executing that one and so on. That means every script in your game runs on a single physical core.
Now while this is convenient since you won’t run into problems that you normally would if you were writing your code in a language that supports actual multithreading, this becomes a bit problematic when you try to do more complex stuff like real-time terrain generation, doing real-time raytracing, mining bitcoins on a poor 8 year old’s 6 year old PC (Please don’t do cryptocurrency mining on someone else’s computer please. This is just a terrible joke.), ect. as that takes too many computing power that developer doesn’t have in a specific timeframe. Which is where Roblox’s Parallel Lua Beta and desynchronized thread
s comes in.
Now to explain how Roblox’s multithreading works, I need to explain you how Luau works a bit on core level. Now in Luau, the code is compiled into bytecode first then that bytecode is run on a Luau process virtual machine (Before you ask, no, it’s not the same thing as operating system virtual machines.). Now because of how Luau Virtual Machine is designed, they can’t really do anything that’s actually multithreaded.
The way Roblox got around this problem is that they implemented an Actor Model with Actor
instances, which is in short terms, you separate your place into different chunks of Actor
instances that gives your code ability to run on desynchronize threads at request (Which is possible with task.desynchronize
or RBXScriptSignal:ConnectParallel
for events.) by using separate Luau Virtual Machines that runs in separate physical cores in your CPU, as long as you’re not trying to access anything else that is outside of that Actor
instance while in desynchronized mode, that is (You can get out of desynchronized mode by using task.synchronize
).
Of course while this is cool and all, this creates some restrictions for a sizeable amount of properties and functions of instances because of how multithreading works as 2 separate threads that are not synchronized in relation to each other might mutate the instance hierarchy while ignoring each other and might create unwanted results. These properties are marked as Unsafe
to be used by unsynchronized threads which is where our issue arises.
Now, I don’t know why accessing Touched
and TouchEnded
events might cause problems (Maybe they forgot or there is some technical reason behind it but I’m not a Roblox engineer that worked on the beta so what do I know?) but you somehow, somewhere in your code try to access BasePart.Touched
event in a desynchronized thread and that is causing some issues, so you need to search for either task.desynchronize
or :ConnectParallel
functions in your code and modules and synchronize the thread, connect the event then desynchronize the thread
or get rid of Actor
implementation altogether from your code.