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!
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)
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)