Raycast mirror origin and direction

I’m trying to make a bullet penetration system, so far I’m just trying to make the barebones and allow it to get the width of a part so I can do the math later.

I’m trying to get the width of a part by raycasting to one side, then raycasting from the other side to where the first raycast hit. The problem is I need to be able to move the second raycast’s origin to maybe 100 studs in front of where it hit, the direction is toward where the first raycast hit the part. In other words I’m having a problem with manipulating the Vector3 values.

There is of course a problem with it being 100 studs from the start, if it were to hit a mesh, depending on the shape, it could hit it in the wrong place. This is a problem for another day, but 100 or even 50 studs would give plenty of room for as much wall penetration as needed.

I’ve searched for it in many different ways and haven’t found any way to achieve it. Although it probably a really simple task. Any help is appreciated.

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()

local mouse = player:GetMouse()

local function CalculatePenetrationDistance(hit, mouseHit)
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Include -- Only detects the part that was hit in the first raycast
	raycastParams.IgnoreWater = true
	
	local rayOrigin = char.HumanoidRootPart.Position
	local rayDestination = mouseHit

	local rayDirection = rayDestination - rayOrigin
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection)
	
	-- Found part.
	if raycastResult then
		local secondRayOrigin = nil -- This is the part that stumps me.
		raycastParams.FilterDescendantsInstances = {raycastResult.Instance}
		
		local raycastResult1 = workspace:Raycast(secondRayOrigin, raycastResult.Position - secondRayOrigin, raycastParams)
		
		if raycastResult1 then
			--Found second part.
			return (raycastResult.Position - raycastResult1.Position).Magnitude
		end
	end
end

mouse.Button1Down:Connect(function()
	print(CalculatePenetrationDistance(mouse.Target, mouse.Hit.Position))
end)

I set the secondRayOrigin variable to nil because I believe its what I need to manipulate to get the origin to move away from the first impact and wanted to make it less confusing. You could think of this system as if the raycasts are mirrored across the part.

Offset your hit point by RayDirection * math.max(HitInstance.Size.X, Size.Y, Size.Z) and then raycast backwards towards origin. You can use RaycastParams to prevent the ray from hitting any other objects other than HitInstance.

This should work for most cases, but if you want to have a max penetration distance for your bullets you can use that in place of Size. Then if it hits nothing then the part is too thick for your bullet to penetrate.

1 Like

Can you explain a bit more? You want a bullet to hit something, then make a second raycast like this to know if the bullet will go trough?
image
(blue bullet, brown second raycast)

1 Like

So I wanted to just find the distance between the two points, that way I can subtract that from a penetration amount variable.

If I had a wall that was 2 studs wide and I shot at it square, and my gun had 5 studs of penetration in the first place. I would have 3 studs left. If that explains it any better.

1 Like

Use the PenetrationAmount variable to find the second origin then. NextOrigin = HitPoint + (RayDirection * PenetrationAmount). If your cast doesn’t hit anything then the part you hit is too thick for your bullet to go through.

1 Like

try something like this: (paste in local script inside tool with handle)

local ContextActionService = game:GetService("ContextActionService")
local rs = game:GetService("ReplicatedStorage")

local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()

local tool = script.Parent
local mouse = plr:GetMouse()

local bm = false
local cdown = 2
local function doSomenting(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.End then
		local originpos = tool.Handle.Position
		local endpos = mouse.Hit.Position
		local direction = (endpos - originpos).Unit 
		local raycast1 = RaycastParams.new()
		local raycastResult1 = workspace:Raycast(originpos,direction * 100)
		
		if raycastResult1 then
			
			local originpos2 = raycastResult1.Position + direction * 10
			print(originpos2)
			--local endpos2 = raycastResult1.Position
			local raycast2 = RaycastParams.new()
			local raycastResult2 = workspace:Raycast(originpos2,-direction * 10)
			
			if raycastResult2 then
				print(raycastResult2.Position)
				print("lenght:",(raycastResult1.Position-raycastResult2.Position).Magnitude)
			end
		end
	end
end

tool.Equipped:Connect(function()
ContextActionService:BindAction("Mouse1Atack", doSomenting, true, Enum.UserInputType.MouseButton1)
end)
tool.Unequipped:Connect(function()
ContextActionService:UnbindAction("Mouse1Atack")
end) ```
1 Like

i think something did i do wrong T-T
Fixed??

It seems to work and you should, like tom_atoes says, use raycast params to only scan for the hited part, substract the “lengh:” value from the rest of the bullet penetration studs, and do a new raycast from the second raycast result, with the same direction and probably less lenght

local secondRayOrigin = raycastResult.Position + rayDirection * bullet_penetration_depth
local raycastResult2 = workspace:Raycast(secondRayOrigin, -rayDirection.Unit * bullet_penetration_depth)
1 Like

did something work? do you get it now?

1 Like

It didn’t work, with the script you gave me the second raycast never hits anything.

1 Like

I think this is progress, as now the second raycast is hitting the part. However the number it returns is not always accurate. Sometimes it is somewhat accurate, other times it is 0.84308413 studs while shooting right through a 4,4,4 block. As for if it just goes through, it doesn’t quite work as expected.

Heres the code if you would like to try it.

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()

local mouse = player:GetMouse()

local function CalculatePenetrationDistance(hit, mouseHit)
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Include -- Only detects the part that was hit in the first raycast
	raycastParams.IgnoreWater = true
	
	local rayOrigin = char.HumanoidRootPart.Position
	local rayDestination = mouseHit

	local rayDirection = rayDestination - rayOrigin
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection)
	
	-- Found part.
	if raycastResult then
		local secondRayOrigin = rayDestination + (rayDirection * 2)
		raycastParams.FilterDescendantsInstances = {raycastResult.Instance}
		
		local raycastResult1 = workspace:Raycast(secondRayOrigin, raycastResult.Position - secondRayOrigin, raycastParams)
		
		if raycastResult1 then
			print("Went through")
			--Found second part.
			return (raycastResult1.Position - raycastResult.Position).Magnitude
		end
	end
end

mouse.Button1Down:Connect(function()
	print(CalculatePenetrationDistance(mouse.Target, mouse.Hit.Position))
end)

okey give me a seconds i will try

i went insane i dont why i did not work but now does?

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()

local mouse = player:GetMouse()

local bullet_pen_studs = 5

function spawnpart(pos,c)
	local part = Instance.new("Part")
	part.BrickColor = c
	part.Anchored = true
	part.Position = pos
	part.Size = Vector3.new(1,1,1)
	part.Parent = workspace
end

local function CalculatePenetrationDistance(hit, mouseHit)

	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Include -- Only detects the part that was hit in the first raycast
	raycastParams.IgnoreWater = true

	local rayOrigin = script.Parent.Handle.Position
	local rayDestination = mouseHit

	local rayDirection = (rayDestination - rayOrigin).Unit
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection * 1000)

	-- Found part.
	if raycastResult then
		spawnpart(raycastResult.Position,BrickColor.Red())
		warn(raycastResult.Instance.Name)
		local secondRayOrigin = raycastResult.Position + (rayDirection * bullet_pen_studs)
		raycastParams.FilterDescendantsInstances = {raycastResult.Instance}

		local raycastResult2 = workspace:Raycast(secondRayOrigin, -rayDirection * (bullet_pen_studs), raycastParams)
		spawnpart(secondRayOrigin,BrickColor.Yellow())
		if raycastResult2 then
			print("went trough")
			spawnpart(raycastResult2.Position,BrickColor.Green())
			--Found second part.
			return (raycastResult2.Position - raycastResult.Position).Magnitude
		end
	end
end

mouse.Button1Down:Connect(function()
	print(CalculatePenetrationDistance(mouse.Target, mouse.Hit.Position))
end)

I think it was the way of raycasting, mouse.Hit.Position sometimes can make you miss the part or something idk

And it keeps hiting the character
And 1 stud is less than you think, its really hard go trough a 1 stud wide wall with 1 stud of penetration

That appears to be working. Thank you guys for helping me out.

1 Like

Make the direction -rayDirection * PenetrationDistance for the second raycast.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.