You need to re-position the place you raycast the ‘penetration raycast’ from. Here’s an example I made up for a simple wall-bang system;
Here you can see some parts, one being labelled A
and the others being labelled E
. The parts labelled E
are simply just some enemies. And A
is simply just the place you shoot from.
You can also see the ‘lines’ which are either connected ‘E-E’ ( enemy to enemy ) or ‘A-E’ ( origin to enemy ). These lines are visualized raycasts.
The code is rather lengthy to get into so I’ll just provide you with the code, and maybe you’ll learn some things:
-- variables
local a: Part = workspace.A
-- functions
local function VisualizeRaycast(raycastResult: RaycastResult, originVector: Vector3)
local distance: number = (originVector - raycastResult.Position).Magnitude
local thickness: number = 0.1
local linearLine: Part = Instance.new("Part")
linearLine.Anchored = true
linearLine.CanCollide = false
linearLine.Size = Vector3.new(thickness, thickness, distance)
linearLine.CFrame = CFrame.lookAt(originVector, raycastResult.Position) * CFrame.new(0, 0, -(distance / 2))
linearLine.Color = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255))
linearLine.Parent = workspace
return linearLine
end
local function Shoot(origin: Vector3, direction: Vector3, penetrations: number)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {a} -- you can add whatever else you want to the blacklist
local raycastResult: RaycastResult = workspace:Raycast(origin, direction, raycastParams)
if (raycastResult) then
local enemy: Part = raycastResult.Instance -- we have to remember that this is the first enemy we hit
VisualizeRaycast(raycastResult, origin)
-- we'll use this 'currentOrigin' variable to make sure the raycast(s) are being shot properly at each position.
local currentOrigin: Vector3 = raycastResult.Position
while (penetrations > 0) do
penetrations -= 1
local newRaycastResult: RaycastResult = workspace:Raycast(currentOrigin, direction, raycastParams)
if (newRaycastResult) then
local anotherEnemy: Part = newRaycastResult.Instance -- this is the enemy which got hit through the wall or whatever you wall banged it from
VisualizeRaycast(newRaycastResult, currentOrigin)
-- set the origin raycast position for the next raycast to use.
currentOrigin = newRaycastResult.Position
end
end
end
end
-- whenever you shoot the gun, you'd call this function:
Shoot(a.Position, a.CFrame.LookVector * 100, 1)
The function ‘Shoot’ is just the function you use every time you shoot the gun. It takes in three arguments; ‘Origin Position’ which is a Vector3 type, ‘Direction’ which is a Vector3 type, ‘Penetrations’ which is how many times the function will iterate over raycasts ( similar to your system ).
Remember that the direction must be correct otherwise your gun won’t shoot in the correct direction.
Just a reminder this ‘system’ is super bare bones and nothing too insane, but maybe you’ll get something out of it.