Do you think a .Touched event is better than Raycasting for combat style games?

So I recently coded a combat system with different swords. You can see some of the LocalScript’s code here, where I utilize a .Touched event on the provided weapons:

	Mouse.Button1Up:Connect(function() -- Animplay
		if Busy == true then return end
		if Wielding == false then return end

		value = math.random(1,5)

		local Hit = LoadAnims.Hits["Hit"..value]

		Hit:Play()
		wait()
		Busy = true

		Detector.Touched:Connect(function(hit) -- TOUCHED EVENT
			if Busy == false then return end
			if Registered == true then return end
			if Blocking == true then return end

			local Hum = hit.Parent:FindFirstChild("Humanoid")
			local Block = hit.Parent:FindFirstChild("blockPart")
			local Detector = hit.Parent:FindFirstChild("Detector")

			if Hum then
				if Hum.Parent.UpperTorso.blockPart:GetAttribute("blocking") == true then return end
				HitRegistered:FireServer(Dmg, Hum, nil, nil, nil, Sounds)
				Registered = true
			elseif Detector then
				if Detector.Parent.Parent.Parent.UpperTorso.blockPart:GetAttribute("blocking") == true then return end
				Registered = true
				LoadAnims.Other.Parry:Play()
				HitRegistered:FireServer(nil, nil, Detector, nil, nil, Sounds)
				repeat Busy = true	
					wait()
				until LoadAnims.Other.Parry.IsPlaying == false
				Busy = false
			elseif Block then
				if not Block:GetAttribute("blocking") == true then return end
				Registered = true
				HitRegistered:FireServer(nil, nil, nil, Block, Blockage, Sounds)
			end
		end)

		repeat wait() until Hit.IsPlaying == false
		Busy = false
		Registered = false
		LoadAnims.Hold:Play()
	end)

But I recently started looking at other developer’s work and tutorials and I found that some people use Raycasting for their combat systems, where they create a ray, cast it from a Character’s HumanoidRootPart, and fire an event if it hits a certain object (like someone’s Humanoid).

I was wondering if that was a better option than a .Touched event, or if it is arguable as to what is better? I know Rays can be harder to use but I feel like I might’ve used a rudimentary method here so I came to ask which was better.

Feel free to comment on any inefficiencies with my code or if you’d like to know more about how my system works btw

No .Touched is horrible for anything you need direct detection exactly at that second. I’m biased, but I always prefer magnitude over raycasting. Some people prefer region3 > all 3 methods are better than touched in general. The only time you really should be using touched is for like kill parts or something like that. If youre doing combat you usually want things to be pretty direct and function exactly when things trigger. Touched is too slow to rely on thats why so many people opt in for region3, magnitude, raycast instead.

3 Likes

Region3 and raycasting are your best options.

Here, I found this super epic hot function made by XAXA

function PartToRegion3(part)
	local abs = math.abs

	local cf = obj.CFrame -- this causes a LuaBridge invocation + heap allocation to create CFrame object - expensive! - but no way around it. we need the cframe
	local size = obj.Size -- this causes a LuaBridge invocation + heap allocation to create Vector3 object - expensive! - but no way around it
	local sx, sy, sz = size.X, size.Y, size.Z -- this causes 3 Lua->C++ invocations

	local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = cf:components() -- this causes 1 Lua->C++ invocations and gets all components of cframe in one go, with no allocations

	-- https://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
	local wsx = 0.5 * (abs(R00) * sx + abs(R01) * sy + abs(R02) * sz) -- this requires 3 Lua->C++ invocations to call abs, but no hash lookups since we cached abs value above; otherwise this is just a bunch of local ops
	local wsy = 0.5 * (abs(R10) * sx + abs(R11) * sy + abs(R12) * sz) -- same
	local wsz = 0.5 * (abs(R20) * sx + abs(R21) * sy + abs(R22) * sz) -- same
	
	-- just a bunch of local ops
	local minx = x - wsx
	local miny = y - wsy
	local minz = z - wsz

	local maxx = x + wsx
	local maxy = y + wsy
	local maxz = z + wsz
   
	local minv, maxv = Vector3.new(minx, miny, minz), Vector3.new(maxx, maxy, maxz)
	return Region3.new(minv, maxv)
end

when i first made a fighting game on roblox i used touch events and it turned out pretty bad so i recommend other options like raycasting and region3

Could you explain what this function does? It seems a little hard to me but Ill try replicating it if its the most efficient method

Do you think raycast is the best option? Ive never used region3 and raycast seems easier to use

Well I think now raycasting is probably one of the better options, it just got updated.
Upgraded, Improved, and Faster Raycasts - Updates / Announcements - DevForum | Roblox

So out of the 3 options raycasting is probably the best now considering this update. However I will still always use magnitude over everything unless I need a direct detection in a set direction. For most of my skill magnitude covers everything, but youre free to choose what you want. Raycast is really good to use though so I would think its great if you start with that.

.Touched is an old service, try to use UIS and CAService

Hey what do you mean by that UIS is a service about keyboard functions, etc…, right? I dont think theres a thing thats like the “touch” function on those services.

You’re right; there isn’t. Touched isn’t a service, either. The solutions posted prior to his are valid.