How do I check if local player has any objects nearby in x z axis

Hello, I am making an event for my game which used to spawn zombies all around the map with a smart AI.

But I couldnt get that to work properly so I decided to make a system where a script would check if there is one or more objects ( such as parts and models except for humanoids ) near a player in the x - z axis. For example, if there is a part that is next or in front of a player that has 5 studs magnitude between, It would not spawn a zombie from that direction

I did research from other posts but they never helped and I don’t really know how Rays work : (

Use the magnitude function to check distance

There are two ways to achieve this, let me present you all of them:

  1. Raycasting. Casting a ray is extremely easy and that’s one of the things you should learn as it is very useful. Creating a ray and receiving information goes like this:
local Origin = --Where the ray should start
local Destination = --Where the ray should reach to
local Direction = --Direction formula: Destination - Origin

--[[ If you want to blacklist objects from getting detected by the ray,
you can use something called RaycastParams as shown here:
--]]
local RaycastParameters = RaycastParams.new()
-- Now follow this documentation to finish the parameters: 
--https://create.roblox.com/docs/reference/engine/datatypes/RaycastParams

function CastRay()
    local Result = workspace:Raycast(Origin, Direction) -- We fire the ray
    -- The result variable returns the ray's information for us
    -- If the ray didn't hit anything, no ray information returns so Result will be nil
    -- So we need to check if Result is nil or not, to prevent errors.
    if Result then
        --Now here's the information you can get out of the Result variable.
        local PartTheRayHit = Result.Instance
        local PositionTheRayStoppedAt = Result.Position
        local RayHitPartMaterial = Result.Material
        local HitPartNormal = Result.Normal
        local DistanceBetweenRayAndHitPart = Result.Distance

    end
end

CastRay()
  1. Looping through all the game’s descendants/children and then checking the distance of each between the player and that instance. This might not be a great idea performance-wise but I’ll still provide the code:
local Players = game:GetService("Players") -- Service gets created in case the game can't find it.
local Player = Players:WaitForChild("player_name_here")
local Character = player.Character or player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

for _, descendant in ipairs(workspace:GetDescendants()) -- or children
    local DistanceX
    local DistanceZ
    if descendant:IsA("BasePart") then
        DistanceX = (HumanoidRootPart.Position - descendant.Position).X
        DistanceZ = (HumanoidRootPart.Position - descendant.Position).Z
    elseif descendant:IsA("Model") then
        local ModelPosition = descendant:GetPivot().Position -- Keep in mind that this returns the center position of the model
        DistanceX = (HumanoidRootPart.Position - ModelPosition).X
        DistanceZ = (HumanoidRootPart.Position - ModelPosition).Z
    end
    if DistanceX <= 5 or DistanceZ <= 5 then
        -- Code here
    end
end

Now, I do not know how your game exactly works and your description was not entirely specific so I was not able to make it more understandable for you but for now, I spent 30 minutes coding these two ways for you on this crappy topic-maker-description-writer tab hehe.

You could create a Region3 area that is not very tall and use FindPartsInRegion3 to get a list of nearby things.

I got it working, thanks for sharing!
I made it so it checks less frequently when the player is not moving

I’ll leave the code here;

game.Players.PlayerAdded:Connect(function(player)
	local Character = player.Character or player.CharacterAdded:Wait()
	local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
	local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
	
	local waittime = 1
	local triggered = false
	
	Character:FindFirstChildWhichIsA("Humanoid").Changed:Connect(function()
		if triggered then
			return
		else
			if Character:FindFirstChildWhichIsA("Humanoid"):GetState() == Enum.HumanoidStateType.Running or Character:FindFirstChildWhichIsA("Humanoid"):GetState() == Enum.HumanoidStateType.Swimming or Character:FindFirstChildWhichIsA("Humanoid"):GetState() == Enum.HumanoidStateType.Jumping or Character:FindFirstChildWhichIsA("Humanoid"):GetState() == Enum.HumanoidStateType.Climbing then
				waittime = 0.2
				triggered = true
				repeat wait() until Character:FindFirstChildWhichIsA("Humanoid").MoveDirection == Vector3.new(0,0,0)
				waittime = 1
				triggered = false
			end
		end
	end)
	
	--// With the function above, the script will check players surroundings more frequently when they are moving
	--// I've named the directions based on the View Selector (Top Bar > View Tab > Actions Category)
	
	while wait(waittime) do	
		local raycastParams = RaycastParams.new()
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		raycastParams.FilterDescendantsInstances = {Character}
		local Result = workspace:Raycast(HumanoidRootPart.Position + Vector3.new(0,-1,0), Vector3.new(1,0,0)* 100, raycastParams) --I'm lowering it 1 stud because there can be stuff lower than the Y of the torso
		if Result then
			local PartTheRayHit = Result.Instance
			local PositionTheRayStoppedAt = Result.Position
			local RayHitPartMaterial = Result.Material
			local HitPartNormal = Result.Normal
			local DistanceBetweenRayAndHitPart = Result.Distance
			
			if DistanceBetweenRayAndHitPart <= 12.5 then --doesn't have to be 12.5 studs
				warn("Too close in X (Left)")
			end
		end
		local Result = workspace:Raycast(HumanoidRootPart.Position + Vector3.new(0,-1,0), Vector3.new(-1,0,0)* 100, raycastParams)
		if Result then
			local PartTheRayHit = Result.Instance
			local PositionTheRayStoppedAt = Result.Position
			local RayHitPartMaterial = Result.Material
			local HitPartNormal = Result.Normal
			local DistanceBetweenRayAndHitPart = Result.Distance

			if DistanceBetweenRayAndHitPart <= 12.5 then
				warn("Too close in X (Right)")
			end
		end
		
		local Result = workspace:Raycast(HumanoidRootPart.Position + Vector3.new(0,-1,0), Vector3.new(0,0,1)* 100, raycastParams)
		if Result then
			local PartTheRayHit = Result.Instance
			local PositionTheRayStoppedAt = Result.Position
			local RayHitPartMaterial = Result.Material
			local HitPartNormal = Result.Normal
			local DistanceBetweenRayAndHitPart = Result.Distance

			if DistanceBetweenRayAndHitPart <= 12.5 then
				warn("Too close in Z (Front)")
			end
		end
		local Result = workspace:Raycast(HumanoidRootPart.Position + Vector3.new(0,-1,0), Vector3.new(0,0,-1)* 100, raycastParams)
		if Result then
			local PartTheRayHit = Result.Instance
			local PositionTheRayStoppedAt = Result.Position
			local RayHitPartMaterial = Result.Material
			local HitPartNormal = Result.Normal
			local DistanceBetweenRayAndHitPart = Result.Distance

			if DistanceBetweenRayAndHitPart <= 12.5 then
				warn("Too close in Z (Back)")
			end
		end
	end
	
end)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.