Melee Raycast problems?

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)
2 Likes

I’m a little bit confused on two things:

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?

1 Like

Hi, I’m experimenting with using RayCast as opposed to .Touched - This is because .Touched can often lag.

Secondly, it may possibly be the case. However, I’ve tried adjusting my code and to no prevail

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!

Thanks,
-Tom :slight_smile:

I seem to have fixed my inital issue however ran into this problem also:
It appears to cause damage despite not being in range.

https://i.gyazo.com/b8c2c0d559195740d3befc71d59dd4e6.mp4

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)

Touched is unreliable, raycasting is much, much faster than Touched.

1 Like

Can I interest you in RayCastHitBox Module, its work really good and easy to use

1 Like

Hi, I’ve had a look at this but generally speaking I’m looking to create my own. I’m not quite at his level of coding at the moment.
Thank you!

1 Like

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

1 Like

image

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

I think I saw someone on the forums say they did about a million raycast and it didn’t hugely affect the games performance.

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)

This will then look like:

local distance = (Tool:WaitForChild("Handle").CFrame.p - Pos).Magnitude

...

p.CFrame = CFrame.new(Tool:WaitForChild("Handle").CFrame.p, Pos) * CFrame.new(0, 0, -distance/2)
1 Like

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:

This is the same issue but backwards, you are using a world position as a direction, when a direction should be a unit vector.

Try changing direction into a target position:

local Target = Tool:WaitForChild("Hitbox")["AT1"].WorldPosition

Then create a directional vector by doing this:

local Direction = (Target - Origin).unit

You should then multiply the Direction by whatever range (in studs) that you want the ray to have, for instance when you do this:

local R = Ray.new(Origin, Direction)

Multiply Direction by the distance between the origin and the target as follows:

local R = Ray.new(Origin, Direction*((Origin-Target).Magnitude))

It should be noted that your old code should have worked just fine, and did not have any issues outside of the visualization code.

2 Likes