I can’t just require a module and start calling functions in it, even if my LocalScript isn’t in parallel because the module script I want to communicate with has global state and everything breaks once my LocalScript is in an actor before I’ve even called task.Desyncronize().
When I try to use BindableFunctions I get an error for trying to call a function from another VM. BindableEvents don’t seem to work across VMs though I haven’t done much testing.
How on earth am I supposed to communicate between scripts on different VMs?
Passing closures across VMs would be a blatant violation of thread-safety (What if you passed a function that had an upvalue, and it was deemed constant in one VM when another suddenly mutates to it? Which VM’s garbage collector should collect it?)
You ultimately have two options:
Use SharedTables to sync and update data between VMs
Use bindables to pass by value between VMs
Ironically, Roblox’s SharedTable implementation is extraordinarily slower in comparison to using bindable events, which I have found to still be alarmingly sluggish in comparison to just iterating through a serial thread.
I see. Which bindables are you using? As I mentioned before, I tried using a bindable function and it just threw an error.
Do you think it’s even worth it for me to use an actor? I’m pretty much just making a workspace:GetPartBoundsInRadius call and iterating over the results every frame with some caching to reduce the performance hit. I’m only using an actor so this one module will hopefully run faster.
The issues with communicating across VMs comes from the script that uses this module trying to communicate with other scripts.
local module = {}
if not script.Parent then print(script:GetFullName(), "has no parent") return end
local Character = script:FindFirstAncestorOfClass("Model")
local Humanoid : Humanoid = Character:WaitForChild("Humanoid")
local Root : Part = Character:WaitForChild("HumanoidRootPart")
local LineOfSightParams = RaycastParams.new()
LineOfSightParams.FilterType = Enum.RaycastFilterType.Include
local RadiusCheckParams = OverlapParams.new()
RadiusCheckParams.FilterType = Enum.RaycastFilterType.Include
local NearbyTilesExpiration = 2
local _NearbyTiles = {}
local _NearbyTiles_LastTick = -100
module.Discriminators = {
ClosestPaintedTile = function(tile, point)
return Humanoid.TeamColor.Value == tile.Color
end;
ClosestUnpaintedTile = function(tile, point)
return Humanoid.TeamColor.Value ~= tile.Color
end;
ClosestUnpaintedTileLOS = function(tile : BasePart, point)
local tilePos = tile.Position + Vector3.yAxis * 2.5
local LOShitInfo = workspace:Raycast(point, tilePos - point, LineOfSightParams)
return Humanoid.TeamColor.Value ~= tile.Color and (not LOShitInfo or LOShitInfo.Instance ~= tile)
end;
}
function module:GetTileClosestToDistance(point : Vector3?, radius : number, discriminatorName : string, desiredDistance : number?)
local discriminator = module.Discriminators[discriminatorName]
if not discriminator then error(tostring(discriminatorName).. " is not a valid discriminator function..",2) end
RadiusCheckParams.FilterDescendantsInstances = {workspace.Map.Ground}
LineOfSightParams.FilterDescendantsInstances = {workspace.Map}
task.desynchronize()
if not desiredDistance then desiredDistance = 0 end
-- cache results for a while.
local groundTiles
if not point then
point = Root.Position + (Root.AssemblyLinearVelocity * 1)
if not _NearbyTiles or tick() - _NearbyTiles_LastTick > NearbyTilesExpiration then
_NearbyTiles_LastTick = tick()
_NearbyTiles = workspace:GetPartBoundsInRadius(point, radius, RadiusCheckParams)
end
groundTiles = _NearbyTiles
else
groundTiles = workspace:GetPartBoundsInRadius(point, radius, RadiusCheckParams)
end
local closestTile = nil
local closestDelta = math.huge
for i, tile : BasePart in ipairs(groundTiles) do
if not discriminator(tile, point) then continue end
local distance = (point - tile.Position).Magnitude
local delta = distance - desiredDistance
if math.abs(delta) <= closestDelta then
closestTile = tile
closestDelta = math.abs(delta)
end
end
task.synchronize()
return closestTile
end
return module
you can use MessagingService to enable cross-server messaging between different servers or client instances of your experience. This allows you to communicate between scripts on different VMs. Cross-Server Messaging | Documentation - Roblox Creator Hub
When Roblox developers talk about Lua VMs running in parallel, they are almost always going to be talking about Parallel Luau, not how to communicate between Roblox servers. If I needed help communicating between Roblox servers, I would ask for that.
I appreciate the response, but you’ve misunderstood my question. You should really read a users post before responding.
It’s honestly ridiculous, I spent a day trying to figure out how to send messages between actors and non actors and I ended up just having to use bindable events, which are still affecting my performance because it in serial… Best thing I can do is minimize the amount of data I send through the bindables, my mob AI would allow a lot more mobs to be active if they ran in parallel. I will try using shared tables to send information but it probably will be the same.