How would one make bullet piercing without fast cast or any other api?

  1. I am trying to make a piercing system that can pierce thin walls.

  2. I have no idea how to do this as I suck at math. I currently have this system but it does not have a piercing. GUN Test #1 - YouTube

  3. I have tried to search for answers to help, but I could not find any of use.

(off topic)
I also raycasted and managed all the effects on the client like this… is this fine or should I change it to the server?
(sorry for my really bad coding)


local recoil=require(game.ReplicatedStorage.SpringModule).new()
game:GetService("RunService").RenderStepped:Connect(function(dt)
	local recoil=recoil:update(dt)
	workspace.CurrentCamera.CFrame=workspace.CurrentCamera.CFrame*CFrame.Angles(recoil.X,recoil.Y,recoil.Z)
end)
math.randomseed(tick())

local bul=require(game.ReplicatedStorage.BulletHoles)
local ray=RaycastParams.new()
ray.FilterType=Enum.RaycastFilterType.Blacklist
game.ReplicatedStorage:WaitForChild('events').bulletRep.OnClientEvent:Connect(function(data)
	local ignore={data.sender.Character,workspace.ignoreList}
	for i,v in pairs(game.Players:players())do
		if v.data.team.Value==data.sender.data.team.Value and v~=data.sender then
			table.insert(ignore,#ignore+1,v.Character)
		end
	end
	ray.FilterDescendantsInstances = ignore
	local RandomValue = function(Argument1, Argument2)
		return Random.new():NextNumber(Argument1 or -.1, Argument2 or .1) --Custom Random function cause math.random isent really working for me
	end
	local gun=data.tool
	local position=data.pos+Vector3.new(RandomValue(-.3,.3),RandomValue(-.3,.3),RandomValue(-.3,.3))
	local origin = data.org.Position
	local direction = (position - origin).Unit*300
	local result = workspace:Raycast(origin, direction)
	
	local intersection = result and result.Position or origin + direction
	local distance = (origin - intersection).Magnitude
	local beamStart = Instance.new("Attachment") 
	local beamEnd = Instance.new("Attachment")
	beamStart.Parent,beamEnd.Parent = workspace.Terrain,workspace.Terrain-- a hack bc the terrian counts as an infinite basepart
	beamStart.Position,beamEnd.Position = origin, intersection
	local beam = script.Beam:clone()
	beam.Enabled=true
	beam.Attachment0 = beamStart
	beam.Attachment1 = beamEnd
	beam.Parent = beamStart
	local time = .2 + (distance/200)
	beam.TextureSpeed = 5 - (time*10)
	game:GetService("TweenService"):Create(beamStart,TweenInfo.new(time),{Position=beamEnd.Position}):Play()
	game:GetService("Debris"):AddItem(beamStart,time)
	game:GetService("Debris"):AddItem(beamEnd,time)
	local hit=Instance.new("Part")
	hit.Name='hit_sfx'
	hit.Anchored=true
	hit.CanCollide=false
	hit.Transparency=1
	hit.Position=intersection
	hit.Size=Vector3.new(.05,.05,.05)
	hit.Parent=workspace.ignoreList
	game:GetService("Debris"):AddItem(hit,1.5)
	local sfx=script['Bullet_sound_'..math.random(1,6)]:Clone()
	sfx.Parent=hit
	sfx:Play()
	local Amount=math.clamp(2-(distance/100),0,2)
	if game.Players.LocalPlayer == data.sender then
		Amount = 1.3
	end
	local Value1 = (RandomValue() * 2) * Amount
	local Value2 = (RandomValue()) * Amount
	local Value3 = (RandomValue() / 18) * Amount
	local CalculatedCameraValue = Vector3.new(0.016 * Amount + Value3, Value1 / 24, 0)
	local CalculatedRecoilValue = Vector3.new(Value2/10,Value2/8,-.013)
	recoil:shove(CalculatedCameraValue)
	spawn(function()
		wait(0.15)
		recoil:shove(-CalculatedCameraValue)
	end)


	for i,v in pairs(gun.muzzle.effects:children())do
		v:Emit(10)
	end
	local sfx=gun.muzzle.fire:clone()
	sfx.Parent=gun.muzzle
	sfx:play()
	game.Debris:AddItem(sfx,3)
	if result then


		local part = result.Instance
		local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")

		if humanoid then
			if p == data.sender then
				game.ReplicatedStorage.events.takeDmg:fireServer(data.damage,humanoid)
			end
			local hit = result.Instance
			local hole=bul:New(hit,intersection,1,'rbxassetid://5427017132')
			local DebrisAttachment=Instance.new("Attachment",workspace.Terrain)
			DebrisAttachment.Position=intersection
			local DebrisEffect = game.ReplicatedStorage.hit:Clone()
			local Effect=DebrisEffect
			Effect.Enabled=true
			Effect.Parent=DebrisAttachment
			coroutine.resume(coroutine.create(function()
				wait(.2)
				Effect.Enabled=false
				wait(1)
				DebrisAttachment:Destroy()
			end))
			local DebrisAttachment=Instance.new("Attachment",workspace.Terrain)
			DebrisAttachment.Position=intersection
			local DebrisEffect = game.ReplicatedStorage.spray:Clone()
			local Effect=DebrisEffect
			Effect.Enabled=true
			Effect.Parent=DebrisAttachment
			wait(1)
			Effect.Enabled=false
			wait(4)
			DebrisAttachment:Destroy()
		else
			local hit = result.Instance
			local hole=bul:New(hit,intersection,1)
			local DebrisAttachment=Instance.new("Attachment",workspace.Terrain)
			DebrisAttachment.Position=intersection
			local spark=script.Spark:clone()
			spark.Parent=DebrisAttachment
			spark:emit(10)
			local DebrisEffect = game.ReplicatedStorage.debris:Clone()
			local Effect=DebrisEffect
			Effect.EmissionDirection = hole.Face
			Effect.Color = ColorSequence.new(result.Instance.Color)
			Effect.Enabled=true
			Effect.Parent=DebrisAttachment
			wait(.5)
			Effect.Enabled=false
			game.Debris:AddItem(DebrisAttachment,2)
		end
	end
end)

I have tried every way to make a piercing, but I could not find out how. Help would be appreciated.

8 Likes

You could use a raycast to check the wall width, length and height depending on your criteria of a thin wall you can ignore the wall, creating a pierce effect. I hope i made sense.

EDIT:
So what i mean by this is before you fire the bullet you can cast a ray to do a criteria check if a part is within the requirements to be pierced, how you could do this is by collision filtering…

2 Likes

But how would one do that? Im thinking of raycasting the opposite direction a few studs infront of the intersection to see if there is a pierceable wall. Like this (ms paint, sorry if its unreadable):
pierce sketch

3 Likes

Thats a good idea, i never thought of that!

1 Like

So you want Ricochet not pierce?

1 Like

I do want to pierce, but i will try to add ricocheting myself

1 Like

Just want to clarify is local hit the bullet?

1 Like

No no, local intersection is. local hit is just a part created for a small amount of time so it can play sounds at the hit position
edit:
local intersection is the position of the hit, the beam is the bullet

1 Like

Oh my bad :sweat_smile: here i thought that the bullet was a part that called bullet and you simply tweened it, i see now then you can forget about collision filtering let me see if i can propose another idea.

1 Like

image
the yellow is the bullet and the blue is the 2nd raycast. if the bullet hit a part, it will create a second raycast that looks at the hit position. if the 2nd raycast is hit, this means the wall is pierceable so you carry on the bullet.

2 Likes

i have not tested this, so idk if it works

1 Like

Thats what i said at the start but i can clarify a little more on how you can accomplish this.
Raycasts have an option called ignore i believe you are aware of this. Before you fire a bullet you can do a simple raycast to do the following steps…

  1. Is the ray hit a player or part?
  2. If player then use your current code as normal
  3. If part then check the parts width and length to see if the wall is thin (in your criteria)
  4. If wall not thin then continue with your current code
  5. If it is a thin wall make sure you create ignore variable with the part object.
  6. Fire your bullet raycast and ignore the part
1 Like

Thank you, but i have no idea how to get the width and length. Do you simply use the size or do you use math to figure it out? Im trash at math so I’m really confused. Another thing thats off topic, should i raycast on the client or the server? when the gun is fired, a remote event is fired that tells all clients to show this bullet. i heard that you should raycast on the server bc its fine on performance

Wait i thought this was server-side, if not I DEFINITELY recommend you do server-side with this simply use remote events, you seem capable so i will leave how you do that to you.

As for how to get the part size, in your perspective do result.Size that should give you a vector3 value with (width,length and height)

EDIT: example of width

if result.Size <= Vector3.new(0,0.5,0) then
    ignore = result

Damn it, i have to redo the camera system then and i need new remotes

1 Like

I still dont get this, why use size when you might be shooting at a wall at diff angles?
image
if i shot here it would still pierce cause the size wont change, its just size.

Ill have a look into it, thanks.

RaycastResult | Documentation - Roblox Creator Hub - more specifically

Wait so normal in this cause, would be the size? Have i finally learnt what normal is?