I’m working on a Raycast based Melee system:
However, for some reason it chooses not to display properly in-game whilst trying to visualise the RayCast.
script.Parent:WaitForChild("RemoteEvent").OnServerEvent:Connect(function(Player, Tool)
local Humanoid = Player.Character:WaitForChild("Humanoid")
local Slash = Humanoid:LoadAnimation(script:WaitForChild("Slash"))
Slash:Play()
repeat wait()
local R = Ray.new(Tool:WaitForChild("Handle").CFrame.p, Tool:WaitForChild("Handle").CFrame.UpVector * 5)
local PartFound, Pos = workspace:FindPartOnRay(R, Humanoid.Parent)
local distance = (Tool:WaitForChild("Handle").CFrame.p - Tool:WaitForChild("Handle").CFrame.UpVector * 5).Magnitude
local p = Instance.new("Part")
p.Parent = workspace
p.Anchored = true
p.CanCollide = false
p.Size = Vector3.new(0.1, 0.1, distance)
p.CFrame = CFrame.new(Tool:WaitForChild("Handle").CFrame.UpVector * 5, Tool:WaitForChild("Handle").CFrame.p) * CFrame.new(0, 0, -distance/2)
if PartFound then
print(PartFound.Name)
break
end
until Slash.IsPlaying == false
end)
Firstly may I ask why raycasting is being used in a melee system?
Secondly, are you sure that the ray is showing as being wrong, and you’re sure the ray itself isn’t wrong?
Personally I would say that raycasting would be a little slower and more latent than the Touched method, and whenever I’ve created melee systems Touched events have been the most reliable methods.
If you can do a few experiments that prove raycasting is more time consuming and responsive then I’d love to hear about it!
script.Parent:WaitForChild("RemoteEvent").OnServerEvent:Connect(function(Player, Tool)
local Target
local Humanoid = Player.Character:WaitForChild("Humanoid")
local Slash = Humanoid:LoadAnimation(script:WaitForChild("Slash"))
Slash:Play()
repeat wait()
local Origin = Tool:WaitForChild("Handle").CFrame.p
local Direction = Origin + Tool["Handle"].CFrame.UpVector * Tool["Hitbox"].Size.Y / 2
local R = Ray.new(Origin, Direction)
local PartFound, Pos = workspace:FindPartOnRay(R, Humanoid.Parent)
local distance = (Origin - Direction).Magnitude
local p = Instance.new("Part")
p.Parent = workspace
p.Anchored = true
p.CanCollide = false
p.Size = Vector3.new(0.1, 0.1, distance)
p.CFrame = CFrame.new(Direction, Origin) * CFrame.new(0, 0, -distance/2)
if PartFound then
if PartFound.Parent:FindFirstChild("Humanoid") ~= nil
or PartFound.Parent.Parent:FindFirstChild("Humanoid") ~= nil then
Target = PartFound.Parent["Humanoid"]
end
break
end
until Slash.IsPlaying == false
if Target then
Target:TakeDamage(5)
end
end)
ok, understandable have a great day, but I think it’s really easy to use and work really good for me, so I recommend it. You don’t have to reinvent the wheel.
This is based on how you’re doing the raycast, if you’re doing the raycast throughout the animation under heartbeat it isn’t certain if it’s faster. Also touched isn’t as bad as most people say it is, maybe under latency it could be unreliable but touched has its uses rather than checking per frame I can have a listener.
The ray display code is wrong.
The UpVector is 0,1,0, therefore it will always make the part go to the world center. Rays use Unit directions: the ray display doesn’t.
Here’s a function i’ve been using for the past few months. you feed in a ray, what it hits, and the timeout before the visualization disappears
Try using this to visualize the ray
Not worth another reply, rather an edit:
I found it literally unbearably laggy in a real game, if it has to do physics with more than 10-20 (maybe more) parts the FPS starts dipping hard and the event itself tends to be very inconsistent in whether it fires or not
Bad depiction of what I wish to achieve.
I’m attempting to make the RayCast from the ‘Hilt’ of the Sword to the ‘Tip’ so that if anything within those boundaries is hit during the time of Swinging, damage is given.
I would use touched, if your looking for something that hits the sword, although it can be unreliable, it’s not that bad at all. Raycasting can be used for combat but I would support trying to use the module @danthemanroblox192 given, for raycasting for melee. If you really still want to do raycasting by yourself with no module, then it would be much easier to have the ray come from someplace else, for example, your torso, head, etc. because you can use things like lookvectors in this case.
I don’t necessarily agree with this, not in that raycasting would be slower, but rather that this really is a non-issue. You can use tens of thousands of raycasts each frame with no performance impact. Raycasting really is a good solution for melee and such an implementation can be seen here: Raycast Hitbox 4.01: For all your melee needs! - #9 by TeamSwordphin
The problem isn’t with your raycasting code, but rather with the visualization code.
You created a part with origin position Tool:WaitForChild("Handle").CFrame.UpVector * 5. This is a unit vector meaning it represents a direction, and should not be used as a location. Instead, try using the position of the raycast:
local PartFound, Pos = workspace:FindPartOnRay(R, Humanoid.Parent)
Hi, It’s genuinely less so with the visual demonstration of it at the moment. It’s the actual slashing // collision I’m having difficulties with.
I changed the Ray Origin & Position into two attachments instead.
script.Parent:WaitForChild(“RemoteEvent”).OnServerEvent:Connect(function(Player, Tool)
local Target
local Humanoid = Player.Character:WaitForChild("Humanoid")
local Slash = Humanoid:LoadAnimation(script:WaitForChild("Slash"))
Slash:Play()
repeat
local Origin = Tool:WaitForChild("Hitbox")["AT0"].WorldPosition
local Direction = Tool:WaitForChild("Hitbox")["AT1"].WorldPosition
local R = Ray.new(Origin, Direction)
local PartFound, Pos = workspace:FindPartOnRay(R, Humanoid.Parent)
if PartFound then
if PartFound.Parent:FindFirstChild("Humanoid") ~= nil
or PartFound.Parent.Parent:FindFirstChild("Humanoid") ~= nil then
Target = PartFound.Parent["Humanoid"]
end
break
end
wait()
until Slash.IsPlaying == false
if Target then
Target:TakeDamage(5)
Target = nil
end
end)
However, I’m still facing the issue where Damage is being taken despite the Player not being around the target: