Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why is my raycasting detecting more parts than there are around a player?

I am trying to find an empty location around a player for another player to spawn at. Someone suggested raycasting and so that is what I am using. The code works fine when there are no parts around the player. The problem comes when there are some parts. I have a ceiling and two walls I put up to see if my code worked. When I stood under the ceiling and two walls and tried to get the other player to teleport to me, it did not work. So I put some prints in to see where the problem was and apparently my raycasting is detecting parts in all directions even the directions where there are none. Here is the script:

local function findEmptyDirection(character)
	
	local hRPart = character:FindFirstChild("HumanoidRootPart")
	
	if hRPart then
		
		local xYOrZ
		local offset
		
		for i = 1, 5 do
			
			if i == 1 then
				xYOrZ = Vector3.new(0, 10, 0)
				offset = Vector3.new(0, 7, 0)
			elseif i == 2 then
				xYOrZ = Vector3.new(8, 0, 0)
				offset = Vector3.new(5, 0, 0)
			elseif i == 3 then
				xYOrZ = Vector3.new(-8, 0, 0)
				offset = Vector3.new(-5, 0, 0)
			elseif i == 4 then
				xYOrZ = Vector3.new(0, 0, 8)
				offset = Vector3.new(0, 0, 5)
			elseif i == 5 then
				xYOrZ = Vector3.new(0, 0, -8)
				offset = Vector3.new(0, 0, -5)
			end
			
			local ray = Ray.new(hRPart.Position, hRPart.Position + xYOrZ)
			local part, hitPosition = workspace:FindPartOnRay(ray, character)
		
			if not part then
		
				return hRPart.Position + offset
				
			else
				
				print(part.Name) -- this prints 5 times even though there should be only three parts
				
			end
			
		end
			
		return false
		
	end
	
end

Thanks!

1 answer

✓ Accepted answer

Your issue seems to be on this line: local ray = Ray.new(hRPart.Position, hRPart.Position + xYOrZ), more specifically the second argument. It is supposed to be the direction vector, you're now passing it the direction vector translated with the root part's position. Taking out the translation should fix the issue: local ray = Ray.new(hRPart.Position, xYOrZ)

I wrote this little demonstration to capture empty points around the player, in case you want to see a more cleaner approach to the problem:

local character = script.Parent
local root = character.PrimaryPart

--

local function drawPoint(v3, brickColor, parent)
	local part = Instance.new("Part")
	part.Anchored = true
	part.CanCollide = false
	part.BrickColor = brickColor
	part.CFrame = CFrame.new(v3)
	part.Size = Vector3.new(0.5, 0.5, 0.5)
	game:GetService("Debris"):AddItem(part, 0.1)
	part.Parent = parent or workspace
	return part
end

local function isPointEmpty(origin, direction)
	local ray = Ray.new(origin, direction)
	local collision, position = workspace:FindPartOnRayWithIgnoreList(ray, {character})
	return collision == nil, position
end

local function findEmptyPoints(character, segments, radius)
	local emptyPoints = {}
	
	radius = radius or 10
	local rad = math.rad(360 / segments)
	local origin = character.PrimaryPart.CFrame
	
	for i = 1, segments do
		local direction = origin.p - (origin * CFrame.Angles(0, rad * i, 0) * CFrame.new(0, 0, radius)).p
		local isEmpty, position = isPointEmpty(origin.p, direction)
		drawPoint(position, isEmpty and BrickColor.Green() or BrickColor.Red(), character)
		if isEmpty then
			table.insert(emptyPoints, position)
		end	
	end
	
	--	Check above the head
	do
		local direction = Vector3.new(0, radius, 0)
		local isEmpty, position = isPointEmpty(origin.p, direction)
		drawPoint(position, isEmpty and BrickColor.Green() or BrickColor.Red(), character)
		if isEmpty then
			table.insert(emptyPoints, position)
		end
	end
	
	return emptyPoints
end

--

game:GetService("RunService").Heartbeat:Connect(function()
	print(unpack(findEmptyPoints(character, 8, 5)))
end)

1 comment

0

Thank you so much!

This discussion is preserved as it was. New answers, comments, and votes are closed.