I’m trying to make a laser attach to my gun, so I’m calling the function off of the client which will trigger the server script to return the laser beam. However, I am trying to set the length of the beam to the size of ray that is casted out, so the beam works like an actual laser. The issue is I get this error: attempt to index nil with ‘Size’.
Error is called on this line: laser.Size = Vector3.new(0.3, 0.3, dist)
This is the local script
laser = laserRemote:InvokeServer()
spawn(function()
RunService.Stepped:Connect(function()
if laserOn == false then return end
print('Fire a laser')
local direction = Handle.CFrame.LookVector.Unit
local laserRay = Ray.new(Handle.CFrame.p, direction * 2000)
local _,hitPos = workspace:FindPartOnRay(laserRay, Handle, true, true)
local dist = (Handle.CFrame.p - hitPos).magnitude
print(hitPos)
print(dist)
laser.Size = Vector3.new(0.3, 0.3, dist)
laser.CFrame = CFrame.new(Handle.CFrame.p, hitPos) * CFrame.new(0, 0, -dist / 2)
laser.Parent = Handle
wait()
laser:Destroy()
end)
print('End')
return
end)
and this is the server remote function
function LaserRemote.OnServerInvoke()
local laser = IdealLaser:Clone()
return laser
end
The IdealLaser is defined on server, so it’s not an issue of cloning that.
I will also need help setting the network ownership of the laser beam to the client so it doesn’t lag for the client but all other players will still be able to see it, but I can do that later. So if you can figure out the error, please help.
You only create one laser in your script and destroy it at the end of the function. As you’re attempting to do this every step it’s going to error as you destroyed it the first time it ran.
Why are you creating the laser on the server anyway? Any changes you make to it won’t replicate back so only the client who fired will be able to see it
I’m going to set network ownership to client, so everyone can see it. I also will fix it destroying, but that’s not the error right now that I need help with.
Can you explain this a bit more in depth in terms of terminology? What does it mean when something yields? Why not use the spawn() function? Thank you.
Only the client can see the cloned part, so the server reads it as “nil”. You will have to send the information of the laser from the client to the server, and the server then uses the information to create the laser.
The size will never replicate from client to server, regardless of the parts network owner, so, the server has to create the part and manipulate the part, though you can change the part on the client, send the info, and the server will change the part with the info.
When something yields, it means that the script will stop at the line that yielded until it’s done with what it’s supposed to do.
print("hi")
wait(3) --yields for 3 seconds
print("bye") --this isn't executed until the previous line is done
Other stuff that yield would be :WaitForChild(), which will yield until the child to wait for has loaded. You use spawn() and other things like coroutines and delay to stop something from yielding. You’re rately gonna find yourself spawn()ing :WaitForChild() or wait(), you mainly need to spawn() while loops and stuff that will yield forever
print("hi")
while true do
wait()
end
print("bye") --this will never be printed, unless the while loop is spawned
In your code, you spawned the Stepped event, it’s true that Steppedand its variants like RenderStepped keep on doing stuff forever, almost like while loops, although they don’t yield.
print("hi")
game:GetService("RunService").Stepped:Connect(function()
--do stuff
end)
print("bye") --prints this straight away
But even for the server to repeatedly render that for every user with a laser on, that’d reduce game performance I believe. Wouldn’t it be best if the server created the part, but then the client can render the physics for it which everyone would see?
So you mean each frame the client sends the new length of ray to server, which updates the size, and then the client can control its position when it’s moved?
Yes, make sure the Network Owner is the player though, using BasePart:SetNetworkOwner()
Edit: I would still recommend the server doing all the work, laggy players will see a weird order of replication like that
Edit2: RemoteFunction:InvokeClient() isn’t recommended, as an exploiter could just remove the return line and would keep the server hanging forever, and the server should also wrap them in pcall so if the player leaves before the info is received by the server, the error won’t break the script