Been working on a Wand system that doesn’t seem to detect the PartOnRay each time,
As shown below - A majority of the time it will detect the Part and then creates the hit effect so forth, however other times it will pass straight through a solid brick / Player and this proves problematic.
for Movement = 1,math.huge do wait()
if SpellPart then else return end
game:GetService("RunService").Heartbeat:wait()
SpellPart.CFrame = SpellPart.CFrame + SpellPart.CFrame.LookVector * math.random(6, 10)
local SpellRay = Ray.new(SpellPart.Position, (Wand.Tool["Tip"].Position - SpellPart.Position).Unit * 10)
local Obj, Position = workspace:FindPartOnRay(SpellRay, IgnoreList)
if (SpellPart.Position - Position).Magnitude <= 6 then
if Obj.Parent:FindFirstChild("Protego") == nil and Obj.Parent.Parent:FindFirstChild("Protego") == nil then
SpellPart:remove() SpellPart = nil
SpellRayHit(Player, Wand, SpellPart, SpellTrail, Obj, Position)
return
else
SpellPart.CFrame = CFrame.new(SpellPart.CFrame.p, Player.Character["HumanoidRootPart"].CFrame.p)
IgnoreList = nil
end
else end
end
That line would shoot a ray from the spell part back to the wand if I’m not mistaken. It’s possible that in some cases your projectile which moves from math.random(6, 10) studs in distance per heartbeat is further than your ray’s length which is 10 as shown on the line above.
Instead of firing the ray from the projectile back to the wand, it would probably be better to send it from the projectile in the direction of the projectile. That could be done like so by changing the line above to:
local SpellRay = Ray.new(SpellPart.Position, SpellPart.CFrame.LookVector * 20)
This would start the ray at your SpellPart’s position and send it in the direction of the SpellPart. Note that I’ve also made the ray longer (20 studs instead of 10) this should fix the issue you’re seeing.
Hi, this seems to still be causing an issue for me.
Though I have just removed the math.random(6,10) and replaced it with * 5 as a singularity and it doesn’t seem to be causing the issue anymore? Could the momentum combined with the Unit have been causing the issue?
Okay, one more thing I would recommend trying is moving the ray check before moving the SpellRay. It’s possible that the SpellRay is moving through the ground before the ray is casted.
The issue here seems to me that the projectile is going through the ground before the ray has checked for collisions.
There’s actually not even a reason to move the SpellPart if the SpellRay hits something. You could check if the ray hit something and then remove the SpellPart before even moving it.
for Movement = 1,math.huge do wait()
if SpellPart then else return end
game:GetService("RunService").Heartbeat:wait()
SpellPart.CFrame = SpellPart.CFrame + SpellPart.CFrame.LookVector * 5
local SpellRay = Ray.new(SpellPart.Position, SpellPart.CFrame.LookVector * 20)
local Obj, Position = workspace:FindPartOnRay(SpellRay, IgnoreList)
if (SpellPart.Position - Position).Magnitude <= 6 then
if Obj.Parent:FindFirstChild("Protego") == nil and Obj.Parent.Parent:FindFirstChild("Protego") == nil then
SpellPart:remove() SpellPart = nil
SpellRayHit(Player, Wand, SpellPart, SpellTrail, Obj, Position)
return
else
SpellPart.CFrame = CFrame.new(SpellPart.CFrame.p, Player.Character["HumanoidRootPart"].CFrame.p)
IgnoreList = nil
end
else end
end
Give this a try. I added some comments to hopefully help you understand the code a bit better.
local SpellSpeed = 5
for Movement = 1, math.huge do
if not SpellPart then break end
wait()
-- Do ray collision test before moving the SpellPart.
local SpellRay = Ray.new(SpellPart.Position, SpellPart.CFrame.LookVector * SpellSpeed)
local Obj, Position = workspace:FindPartOnRay(SpellRay, IgnoreList) -- Is IgnoreList defined somewhere? It's not shown in your code block.
if not Obj then
-- Ray didn't hit anything, move the SpellPart and test again.
SpellPart.CFrame = SpellPart.CFrame + SpellPart.CFrame.LookVector * SpellSpeed
else
-- Ray hit something. Do collision logic.
if Obj.Parent:FindFirstChild("Protego") == nil and Obj.Parent.Parent:FindFirstChild("Protego") == nil then
SpellPart:remove()
SpellRayHit(Player, Wand, SpellPart, SpellTrail, Obj, Position)
break
else
SpellPart.CFrame = CFrame.new(SpellPart.CFrame.p, Player.Character["HumanoidRootPart"].CFrame.p)
break
end
end
end
I would think IgnoreList is referring to an object, because he’s using FindPartOnRay and not FindPartOnRayWithIgnoreList. @OP I’d recommend that you have your variable names represent what they do, as this shows not to be a list of objects.
EDIT @OP I’m just curious, but why’re you using a ray over a projectile? Wouldn’t it be easier to have a projectile go flying, then when it hits (via Touched) it determines whether it hit a player or not?
The ignore list is simply the Players character, however when it hits a protection spell it repels back into their direction and removes them from the IgnoreList allowing them to be vulnerable to damage.
Just a word of warning to you. If you plan on doing this Raycasting method from the client side you’ll want to verify that the ray actually hit a player. The problem is that it will be impossible to truely verify that because it inevitably requries information from the client to verify. You are almost guaranteed to have issues with exploiters who manipulate the data being sent to the server for verification. There are ways to make it trickier for an exploiter to manipulate the verification but there is no way to totally secure it.
You can also do the raycasting from the server side but that also comes with its downsides. It’s going to feel slower for the client since there is a delay between client and server communications. This is a far more secure method, however.
The .Touched approach is also something that can be handled server side. Since the server handles physics separately from the client there’s almost no way the client can manipulate this, assuming you’re checking for touches server side. This does come with the same draw back as the server-side raycasting method above.
Once you utilize any method online you will find that there are inherent drawbacks to each. You sacrifice security for speed or vice versa. Just keep these things in mind as you implement your projectile logic so that you don’t need to do a major overhaul down the road.
The .Touched approach is also something that can be handled server side. Since the server handles physics separately from the client there’s almost no way the client can manipulate this.
If we’re talking about a projectile launched from the wand, you’re gonna have to manually call SetNetworkOwner() on it. If you don’t, there are probably going to be some edge cases where the client is automatically assigned to it. When the server sets up the Touched event for a part that has a client as a network owner, he is effectively setting up a remote event, asking for the client to tell it whenever it hit something.
You can see this problem in the infamous “range hack” on old-school swords by extending the length of the handle locally (that the client is automatically assigned to).
Actually, without seeming like an idiot This actually worked.
Turns out I was updating it to a version of the Wand that wasn’t even being used by the Player itself!
Trust me to do that!