How should i go about detecting if theres anything within a certain radius without loops and pre-defining players and npc?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!

I want to have a mine that damages all players and NPCs inside a certain radius.

  1. What is the issue? Include screenshots / videos if possible!

Currently, I have the script spawning an invisible sphere and detects if anything touches it but it seems to detect only one thing and damage that and then not do anything.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I tried to search for solutions but couldn’t find any.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

I don’t want the explosion itself do the killing since i want to change the damage etc myself and i have a custom explosion set up.

Edit: To clarify the thing about not having the explosion killing, I meant that the Roblox explosions themselves single-shot players and NPCs which I don’t want.

local blastRadius = 45
local Damage = 250

script.Parent.Touched:Connect(function(part)
	if part.Parent:FindFirstChild("HumanoidRootPart") then
		local explosion = Instance.new("Explosion",workspace)
		explosion.Position = script.Parent.Position

		local blastSphere = Instance.new("Part",script.Parent.Parent)
		blastSphere.Shape = Enum.PartType.Ball
		blastSphere.Transparency = 0.9
		blastSphere.Material = Enum.Material.Neon
		blastSphere.Anchored = true
		blastSphere.Size = Vector3.new(blastRadius,blastRadius,blastRadius)
		blastSphere.Position = script.Parent.Position
		blastSphere.CanCollide = false

		blastSphere.Touched:Connect(function(part)
			
			if part.Parent:FindFirstChild("HumanoidRootPart") then
				part.Parent:WaitForChild("Humanoid"):TakeDamage(Damage)
				print("Damaged: "..part.Parent.Name)
			end
		end)
		script.Parent.Parent:Destroy()
	end
end)

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

1 Like

I’m thinking maybe you could use BasePart:GetTouchingParts() on a sphere part and then do the damage based on the sphere’s touching parts? The sphere could be welded to the HumanoidRootPart. You could also probably make it work with your blastSphere object.

https://developer.roblox.com/en-us/api-reference/function/BasePart/GetTouchingParts

The CanCollide on the invis sphere is false tho

It should still be able to detect collisions as long as the characters’ collisions are set to true (I don’t think you’re able to disable it either).

so should i do something like this:

local blastPart = blastSphere:GetTouchingParts()
for i = 1, #blastPart do
	if blastPart.Parent:FindFirstChild("HumanoidRootPart") then
		-- do stuff
	end
end

Yeah something like that should work but you’d have to do blastPart[i].Parent instead. Also I would recommend checking if blastPart[i]'s name is HumanoidRootPart so you don’t damage too many times

Surprisingly doesn’t work for me, not sure what I did wrong but just pasting that in doesn’t do anything.

You can add a TouchInterest to a non colliding part if you want to listen to touches I believe.

Or, use something like an Octree or K-D tree to partition 3D space and make questions like this faster to answer.

@Quenty has an implementation of an octree here, but I’m sure there are others.

A simple loop wouldn’t be slow, though.

this damages the npc and player multiple times, leading them to get killed in a single blow, ive set the damage to 45 and both the player’s and the npc’s hp is set to 100

script.Parent.Touched:Connect(function(part)
	if not part.Parent:FindFirstChild("Humanoid") then return end
	
	local explosion = Instance.new("Explosion")
	explosion.Position = script.Parent.Position
	explosion.Parent = workspace

	local blastSphere = Instance.new("Part")
	blastSphere.Shape = Enum.PartType.Ball
	blastSphere.Transparency = 0.9
	blastSphere.Material = Enum.Material.Neon
	blastSphere.Anchored = true
	blastSphere.Size = Vector3.new(blastRadius,blastRadius,blastRadius)
	blastSphere.Position = script.Parent.Position
	blastSphere.CanCollide = false
	blastSphere.Parent = script.Parent.Parent
	blastSphere.Touched:Connect(function() end)
		
	local alreadyDamaged = {}
	for _, v in next, blastSphere:GetTouchingParts() do
		local character = v:FindFirstAncestorWhichIsA("Model")
		local humanoid = character and character:FindFirstChild("Humanoid")
		
		if humanoid and not alreadyDamaged[humanoid] then
			alreadyDamaged[humanoid] = true
			humanoid:TakeDamage(Damage)
			print("Damaged: " .. character.Name)
		end
	end
	
	script.Parent.Parent:Destroy()
end)

The blast sphere doesnt detect anything else other than the part that detects if the player steps on the mine, i put a print(blastPart[i]) to the for loop and that shows that only the trigger part of the mine is getting detected

This damages me and the npc twice

Edit: nevermind you just changed the script.Parent.Parent:Destroy() to blastSphere:Destroy() for whatever reason which meant that the mine wasn’t getting deleted and thus activated multiple times

Yeah, it works now, still don’t get why you changed the script.Parent.Parent:Destroy() since that essentially made the mine able to be triggered endlessly

I don’t think you should use .Touched, just use :GetTouchingParts once you want the characters to take damage. You also have to create a TouchInterest inside of the part as @ nicemike40 said.

I think you can use collision groups and it should still be able to detect collisions as both parts would have CanCollide set to true.

local function doExplosion()
    local explosion = Instance.new("Explosion",workspace)
    explosion.Position = script.Parent.Position

    local blastSphere = Instance.new("Part",script.Parent.Parent)
    blastSphere.Shape = Enum.PartType.Ball
    blastSphere.Transparency = 0.9
    blastSphere.Material = Enum.Material.Neon
    blastSphere.Anchored = true
    blastSphere.Size = Vector3.new(blastRadius,blastRadius,blastRadius)
    blastSphere.Position = script.Parent.Position
    blastSphere.CanCollide = false
    local touchingParts = blastSphere:GetTouchingParts()
    for i, part in pairs(touchingParts) do
        if part.Name == 'HumanoidRootPart' and part.Parent ~= script.Parent then
            local humanoid = part.Parent:FindFirstChildWhichIsA('Humanoid')
            if humanoid then
                humanoid:TakeDamage(45)
            end
        end
    end
end

I changed it by accident since I was editing a lot of your script.

1 Like