What's the most efficient way to make a slow moving projectile that can hit multiple people, but only once each?

I’m not quite sure how I’d make a slow fireball work with raycasting

Same way a bullet would work. Besides, again you can also use cylindrical casting (like for example casting in a cylinder from the start to end point between movement loops) and use something like GetTouchingParts() to get things within the area. For this or the somewhat bad touched option you would use debounces after checking if there is a humanoid and then if that humanoid has not been damaged before

local damaged = {} --new table for each fireball
if not damaged[humanoid] then
    damaged[humanoid] = true
    --deal damage
end

What I’m saying is that I thought raycasting was instantaneous, I’m not sure how I’d make a slow moving projectile without segmenting it using raycast

Raycasting is virtually instantaneous but who said you cant raycast in steps lol

I mean I could try raycasting in steps but then I’d have to do it in very small intervals to make sure the fireballs wasn’t essentially teleporting forwards. In which case it kind of seems like it’d make more problems than it solves.

I might be wrong though

Still wrong because you can literally just do something like

local velocity = direction*speed
--frame is renderstepped
local startlife = tick()
while tick()-startlife <= lifetime do
    local step = frame:Wait()
    local start = currentpos
    local goal = currentpos+velocity*step
    --do raycasting from start to goal, aka Ray.new(start,goal-start)
    --handle data from raycast
    currentpos = goal
end

It wont really ‘teleport’ no matter what speed you give it considering it updates every frame and the distance traveled per frame is also based on FPS

It isn’t really inefficient, hence why roblox FPS games exist…

2 Likes

Is Raycasting capable of hitting multiple targets grouped together or would I have to do something else to accomplish that

I dont understand what that means but if you are referring to penetration you can re-cast with the same values but an augmented ignore list until it does not hit anything or it hits a prop/wall.

I’m referring to firing the projectile at a tight, close together, large group of people

And…? please explain what this has to do with raycasting or with your fireball

I was under the impression that the raycast would halt when it hit somebody, also under the impression that a single ray can’t hit more than one person. I could be wrong, but it’d seem like if a single ray can’t hit multiple people then a group of people standing nearby one another would only have one person hit when the fireball passed through them

You should probably look over this part of the post again

By same values, i refer to having the same start and goal and essentially loop casting in the case that it hits a player or npc.

So after deliberating and testing every option I’ve been given so far as I can recall (whitelisted ontouch, gettouching parts, Wulfes Raycasting idea) I’ve come to an unsteady solution.

The raycasting idea is entirely a bust from the get go since we aren’t making a bullet, we’re making a fireball. You can’t expand the hit area for a raycast, it hits the exact area it’s told to (or whatever might be blocking it). As a result we made a fancy small slow moving bullet, not a fireball. GetTouching parts was an idea but you’d need to tell the script when to do that, which would likely be done when it hits something. Which would mean you’re just jumping through hoops to get back to OnTouch. You could theoretically do some 3D math and set zones in the air in front of you sequentially to get hit detection but that’d be a lot of math and work and fine tuning.

tl;dr Best solution ended up being what we started with, OnTouch with a table whitelist it checks each hit. Do a tiny debounce if need be but that’s about it.

1 Like

You could always have a script under StarterCharacterScripts, and have it listen for a touched event. I would aim for the H.R.P. if the projectile is large enough. There doesn’t really need to be any scripting inside of the fireball itself with this method, either, besides the code to move it.

The Code in the script would be this:

local HRP = script.Parent:WaitForChild("HumanoidRootPart")
local hum = script.Parent:WaitForChild("Humanoid")
local debounce = false


HRP.Touched:Connect(function(obj)
	if obj.Name == "FireBall" and debounce == false then
		debounce = true
		hum:TakeDamage(100)
	end
	wait(1)
	debounce = false
end)

Thats a terrible idea because first of all that would prevent damage from multiple different fireballs at the same time, it would not replicate because it is poorly made / done locally, or it would be terribly inaccurate because it is done on the server. It would also be pretty bad on client if the projectile isnt being moved on it.

Seems like this is unsolved.


You can achieve this with many Methods;

The first would be using a Dictionary to Store Humanoids that has been damaged already.

Code
local PlayerS = game:GetService('Players')

local function GetCharacter_Func(Part)
--	local plr = PlayerS:GetPlayerFromCharacter(Part:FindFirstAncestorOfClass('Model'))
	local Cha = Part:FindFirstAncestorOfClass('Model') -- plr and plr.Character or 
	local Hum = Cha and Cha:FindFirstChild('Humanoid')
	if Hum then -- plr and
		return Hum -- Cha,plr,
	end
	return nil
end

local Bullets = {}

local Bullet = workspace.Bullet -- Sample

Bullets[Bullet] = {}

Bullet.Touched:Connect(function(TP)
	local Hum = GetCharacter_Func(TP)
	if Hum and not Bullets[Bullet][Hum] then
		Bullets[Bullet][Hum] = true
		Hum:Damage(50)
	end
end)

The second way is to use CollectionService to AddTag to the Humanoid that has been damaged already.

Code
local PlayerS = game:GetService('Players')

local CollectionS = game:GetService('CollectionService')

local function GetCharacter_Func(Part)
--	local plr = PlayerS:GetPlayerFromCharacter(Part:FindFirstAncestorOfClass('Model'))
	local Cha = Part:FindFirstAncestorOfClass('Model') -- plr and plr.Character or 
	local Hum = Cha and Cha:FindFirstChild('Humanoid')
	if Hum then -- plr and Cha and 
		return Cha,Hum -- Cha,plr,
	end
	return nil
end

local Bullet = workspace.Bullet -- Sample

Bullet.Touched:Connect(function(TP)
	local Cha,Hum = GetCharacter_Func(TP)
	if Hum and not CollectionS:HasTag(Bullet,Cha.Name) then
		CollectionS:AddTag(Bullet,Cha.Name)
		Hum:Damage(50)
	end
end)

I commented some stuff out because you said that it must work with NPCs so there is no need to check for the Player Instance etc.


Other methods I wouldn’t use;
Adding a BoolValue to the Damaged Humanoid
Using an Array to store Damaged Humanoids


It’s in a server script under StarterCharacterScripts - it should replicate.

As for the prevent damage from multiple fireballs, I wasn’t thinking about that last night when I wrote that.

Yes but it is still not a good solution because of other things that I listed.

not to mention that no weapon detection should be done on the server side only unless you really love latency.