How to determine if a projectile should penetrate a wall?

As of now, I am scratching on my head on how to determine if a projectile should penetrate a wall.

The goal of this is to determine if a projectile should go through a wall/part.

I was originally thinking I would use Bullet Velocity Magnitude, Penetration Thickness, and Bullet Mass but it wouldn’t exactly work as I would be required to make detailed bullets. Any help on how to determine if a projectile should penetrate a wall would help a lot!

4 Likes

What information is available on the bullets?

I would probably get the distance inside the wall that it needs to cover and then compare that with current velocity. Decrease velocity relative to amount of space covered inside wall. If velocity drops below a certain threshold, the bullet stops at the wall, otherwise it flies through with adjusted velocity. (Threshold would be high enough so that you would never see it travel at a slow pace mid-air)

5 Likes

I was mainly confused on the “formula” of it. I was messing around more and found a alright one but could be improved.

Formula:

local PartMass = Part:GetMass()^Part:GetMass()
local BulletSpeed = math.abs(Bullet.Velocity.Magnitude)

if BulletSpeed > PartMass then
 print("Bullet should go through")
end

:sweat_smile:
It could be improved in my opinion.

Taking the mass to the power of itself seems like a weird relation. That can give really high numbers.

I was thinking more like this: whenever your bullet ray hits a wall, put your ray a little bit further (it’s now inside the wall), then scan again until you hit the part again (i.e. the other side of the wall, from the inside). Now you can calculate the distance that you traveled through the wall. You’d then compare the bullet speed to that distance covered.

If the speed is sufficient, you put the ray a little bit outside of the wall where you left off, and then scan on (now outside of the wall on other side).

3 Likes

I really like @buildthomas’s solution. Here is how I would find the distance the object has to travel to get through the part.

local axes = {
	X = true;
	Y = true;
	Z = true;
}

local min = math.min
local max = math.max

local function getIntersectionLength(cframe, size, origin, destination)
	local cframeInv = cframe:inverse()
	origin = cframeInv * origin
	local direction =  (cframeInv * destination - origin).unit

	local maxEnterTime = -math.huge
	local minExitTime = math.huge
	for axis in next, axes do
		local enterTime = (size[axis] - origin[axis])/direction[axis]
		local exitTime = -(size[axis] + origin[axis])/direction[axis]

		if exitTime < enterTime then
			exitTime, enterTime = enterTime, exitTime
		end

		minExitTime = min(exitTime, minExitTime)
		maxEnterTime = max(enterTime, maxEnterTime)
	end

	if maxEnterTime > minExitTime then
		-- We missed the part
		return 0
	else
		-- Since direction is a unit vector, the distance is really pretty
		return minEnterTime - maxEnterTime
	end
end

Note that I didn’t test this code (I’m on Debian, and too lazy to start a VM) but it shouldn’t be far off from what you need. Just pass in the hit part’s CFrame and Size as well as the bullet’s origin and destination.

In all honesty, origin and destination can be any two points on the bullet’s path and it wouldn’t make a difference. Note that this means that if the part is actually behind the origin (or you place the destination on the wrong side of the origin) then it will still find the intersection distance as if the bullet was traveling backwards. You could add a check to make sure that the minimum enter time is greater than 0 to avoid this if it isn’t desired. But I don’t think it is a bug, it is a feature!

9 Likes