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
There are two ways to achieve this, let me present you all of them:
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()
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.
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)