I’m working on a weapons system for my game that uses a heavily modified version of the laser gun in the “Hit Detection with Lasers” tutorial on the Creator Hub Documentation. My mods are working perfectly as far as I can tell, except for the piercing bullets. In the weapon, there’s a variable called pierced which increases every time it hits an enemy up to the maximum amount allowed (which is maxpierced). The weapon repeatedly fires bullets up until pierced exceeds maxpierced, with each bullet being rendered seperately; while they are separate bullets, they are intended to look like one continuous bullet as seen here:
This is how it’s supposed to look…
…but this is how it actually looks. The highlighted bullet is the second one that was created, so it pierces the enemy but doesn’t deal damage since the Raycast is updated to not do so (explanation below).
The weapon has a part called FirePoint inside it, and the bullets are made to look like they are starting at FirePoint’s Position. However, the Raycast that is used to visualize the bullets actually begins at the character of the player who fired; more specifically, the character’s torso’s NeckAttachment. I’ve tested it out so that the Raycast also starts at FirePoint (as seen in the first example) and it looks perfectly fine, so I’m certain that the issue stems from the actual Raycast starting at NeckAttachment but the visualized bullet starting at FirePoint.
The reason I want it to start at NeckAttachment is so that there are no discrepancies in the weapon’s range; if the range is set to 70, I want it to travel 70 studs maximum, and FirePoint is not meant to be placed exactly the same in each weapon model since it may look like the bullet is not coming out of the gun’s barrel. Here is all the relevant code from the main weapon LocalScript and the LaserRenderer ModuleScript.
Weapon LocalScript
function fire()
local mouselocation = getmouse() -- gets the mouse's location, I've tested this and this doesn't appear to be what's causing the issue
local raycastresult
repeat
local targetdirection = (mouselocation - neckattach.WorldPosition).Unit -- "neckattach" is the NeckAttachment I was referring to
local direction = targetdirection * range -- the weapon's defined range (here, it's 140)
local raycastparams = RaycastParams.new()
raycastparams.FilterType = Enum.RaycastFilterType.Exclude
raycastparams.FilterDescendantsInstances = filtertable -- models are added here and ignored if the loop continues
raycastparams.RespectCanCollide = false
raycastparams.IgnoreWater = false
raycastresult = workspace:Raycast(neckattach.WorldPosition, direction, raycastparams)
local hitpos
if raycastresult then
hitpos = raycastresult.Position
local charmodel = raycastresult.Instance:FindFirstAncestorOfClass("Model") -- see if the bullet hit a model
if charmodel then
local humanoid = charmodel:FindFirstChildOfClass("Humanoid")
local hrp = charmodel:FindFirstChild("HumanoidRootPart")
if humanoid and hrp then -- if true, then a character was detected
table.insert(filtertable, charmodel) -- if a model is in "filtertable", it will not be detected by the Raycast if it loops
end
end
else -- no character was detected, so have the Raycast continue for the rest of its range
hitpos = neckattach.WorldPosition + direction
end
bulletfired:FireServer(tool.FirePoint, hitpos, currentbullettype) -- "bulletfired" calls the same "laserrender" module, allowing the other players to see the bullet
laserrender.createLaser(tool.FirePoint, hitpos, currentbullettype) -- creates the bullet, but it's only visible by the LocalPlayer
pierced = pierced + 1
until not raycastresult or pierced > maxpierced -- if maxpierced is 0 or pierced has exceeded maxpierced, this loop should end
--loop ends here and everything is reset
pierced = 0
timeofpreviousshot = tick()
table.clear(filtertable)
end
LaserRenderer ModuleScript
function LaserRenderer.createLaser(firepoint, endPosition, bullettype)
local startPosition = firepoint.Position
local laserDistance = (startPosition - endPosition).Magnitude
local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
local laserPart = normalbullet:Clone() -- "normalbullet" is a part whose ancestor is ReplicatedStorage
laserPart.Size = Vector3.new(0.2, 0.2, laserDistance)
laserPart.CFrame = laserCFrame
laserPart.Parent = workspace:FindFirstChild("Effects")
game.Debris:AddItem(laserPart, SHOT_DURATION)
end
I understand that this topic might be a little complicated and I may have failed to explain things clearly, so don’t be afraid to ask me to clarify. To reiterate, the problem comes from the fact that the Raycast used to visualize the bullets starts at NeckAttachment, but the bullet is made to appear from the weapon’s FirePoint for cosmetic purposes.