I have been organising a raycast collision detection system using attachments as hitboxes in module scripts; the original position of the attachment would be indexed and then be followed by waiting with spawn() to calculate if the attachment’s position has changed.
What is the issue?
The issue is returning the raycast results to the script that called the module, as the spawn() function creates an alternative thread.
What solutions have you tried so far?
I have tried using coroutines to replace spawn(), but the performance decreases as instead of looping through the entire arrays of attachments simultaneously, it would only loop through on only the first attachment.
-- looping through the part to fetch attachments
for _, child in pairs(part:GetChildren()) do
if child:IsA("Attachment") then
table.insert(dmg, child)
end
end
if dmg ~= nil then
-- loops through the table of attachments
for _, point in ipairs(dmg) do
local oldPos = point.WorldPosition
local hit, pos
spawn(function()
-- wait in order to detect the position change
rs.RenderStepped:Wait()
local newPos = point.WorldPosition
local distance = (newPos - oldPos).Magnitude
local direction = (newPos - oldPos).Unit
-- raycast function
local instance, position = raycast(point, oldPos, direction, distance)
hit, pos = instance, position
end)
-- returns the result to the main script
return hit, pos
end
end
The reason this is happening is because spawn waits before creating the thread whereas coroutines are instant. You could probably use a wait outside of the coroutine before continuing but this kinda eliminates the point of coroutines.
Try something like this:
for i,v in ipairs(dmg) do
local oldPos = point.WorldPosition
local success, hit, pos = coroutine.resume(coroutine.create(function()
rs.RenderStepped:Wait()
local newPos = point.WorldPosition
local distance = (newPos - oldPos).Magnitude
local direction = (newPos - oldPos).Unit
local instance, position = raycast(point, oldPos, direction, distance)
return instance, position
end))
wait()
end
The issue is that the results are stored on the coroutine’s thread, instead of the main thread where the coroutine was spawned. I am able to print the instance detected on the coroutine, but not from the main thread.
for i,v in ipairs(dmg) do
local oldPos = point.WorldPosition
local success, hit, pos = coroutine.resume(coroutine.create(function()
rs.RenderStepped:Wait()
local newPos = point.WorldPosition
local distance = (newPos - oldPos).Magnitude
local direction = (newPos - oldPos).Unit
local instance, position = raycast(point, oldPos, direction, distance)
print(instance) -- prints the detected instance
hit = instance
print(hit) -- prints the detected instance
return instance, position -- somehow returns nothing
end))
wait()
print(hit) -- prints nil
end
The coroutines do not fail, whether if it is spawn() or coroutine.create(). It is just that the generated result from the coroutine cannot be replicated nor returned, I have tried using an object value to index the hit instance directly, but it does not seem to replicate despite printing the result perfectly without erroring.
That’s weird. Have you tried the variable outside of the scope of the coroutine (the thing in your OP) with coroutines?
Also, are you switching between the client/server boundary at any time? If the instance exists on the client but not on the server, it wouldn’t replicate. But then again it worked with spawn which is weird so that’s probably not it. When you tried printing the status, what was the status?
The module is called from the client to enhance performance issue, but it should not trigger any FE consequences as it is simply returning a detected value to the client that called the module.
module.Add = function(x)
local n
local function add(x)
x += 1
n = x
end
local f = coroutine.wrap(add)
print(f) -- function: 0x744c744e124581cd
print(n) -- nil
return n -- returns nil
end
It behaves normally on another module, but not for the raycast module.
https://gyazo.com/e58bf432c655562001144f3e3455a31b
Video for both the local script and the module script.
On line 57, the module script prints it has detected the humanoid root part, but the local script returns result as nil.
no problemo, OOP or not you aren’t using them to make objects, just using them in a script. think of it like a Vector3, it’s an object but it works with any programming style.