How to add penetration to bullets?

i wanna add penetration to my game
depending on the angle of the bullet your bullet may go through a wall if the penetration of the bullet is strong enough just like how penetration works in war thunder

main question: how to calculate the amount of penetration needed to go through a wall depending on the angle


Perhaps this could help you?

The relative armor thickness (x) can be calculated as the actual armor thickness (w), divided by the sine of the angle (θ). It is important to use degrees, not radians, when doing this calculation.
image

(Of course, ignoring the “Use degrees, not radians” part, as Roblox uses radians)

This only works if the “armor” you are penetrating is a rectangular prism or abstracted into a 2-dimensional plane. For more complicated shapes or if you want it to work with Meshparts, you need to measure the thickness from the impact point to the exit point. Using raycasts won’t suffice because there might be gaps in the mesh, and also because of convex decomposition clipping errors.

Here’s my thickness measuring tool that uses spatial query instead in an iterative manner. It can definitely be improved; it has some precision loss that can be fixed, but works as-is. This should give you a general idea of how its done.

Code
local function raycastThickness(part: BasePart, hitAt: Vector3, dir: Vector3, maxDist: number?): number?
    local rcp: RaycastParams = RaycastParams.new()
    rcp.FilterDescendantsInstances = {part}
    rcp.FilterType = Enum.RaycastFilterType.Include
    
    local olp: OverlapParams = OverlapParams.new()
    olp.FilterDescendantsInstances = {part}
    olp.FilterType = Enum.RaycastFilterType.Include
    olp.MaxParts = 1
    
    local extents: number = part.Size.Magnitude
    local extentsRCR: RaycastResult? = workspace:Raycast(hitAt+dir*(extents+1), dir*-(extents+2), rcp)
    if extentsRCR then
        extents = (hitAt - extentsRCR.Position).Magnitude
    end
    extents = math.min(extents, maxDist or math.huge)
    
    local scanRadius: number = math.max(0.1, math.floor(extents*1 +.5)*.02)
    print(`scan radius {scanRadius}`)
    scannerP.Size = Vector3.one*scanRadius
    local scanStep: number = scanRadius * 2
    
    task.spawn(dot, hitAt, Color3.new(1, 0, 0))
    task.spawn(dot, hitAt+dir*extents, Color3.new(1, 1, 0))
    
    local delta: Vector3 = dir*scanStep
    local scanPos: Vector3 = hitAt
    local traveled: number = 0
    local i: number = 0
    while traveled < extents do
        i += 1
        scannerP.Position = scanPos
        if not workspace:GetPartsInPart(scannerP, olp)[1] then
            break
        end
        scanPos += delta
        traveled += scanStep
    end
    
    task.spawn(draw, hitAt, hitAt+dir*traveled, Color3.new(0, 1, 0))
    print(`iterations count {i}`)
    return traveled
end
4 Likes

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