Bullet doesn't like to go through parts who's X or Z size is lower than 2?

  1. What do you want to achieve? Keep it simple and clear!
    I want my bullets to phase/go through these parts(the magenta and yellow one) who’s size is 0.1(Magenta is 0.1 in X and Yellow is 0.1 in Z) using fastcast
  2. What is the issue? Include screenshots / videos if possible!
    Issue
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried finding the surface it’s hitting like if it’s at the front/back or left/right, switched some variables and stuff…

Line(CanRayPierce):

    elseif hitPart.Size.X <= 2 and hitPart.Size.X < hitPart.Size.Z and getRelativeNormal(hitPart, hitNormal) == Enum.NormalId.Left or getRelativeNormal(hitPart, hitNormal) == Enum.NormalId.Right then
		print('1')
		return true
	elseif hitPart.Size.Z <= 2 and hitPart.Size.Z < hitPart.Size.X and getRelativeNormal(hitPart, hitNormal) == Enum.NormalId.Front or getRelativeNormal(hitPart, hitNormal) == Enum.NormalId.Back then
		print('2')
		return true
	elseif (hitPart.Size.X == hitPart.Size.Z) and hitPart.Size.X <= 2 and hitPart.Size.Z <= 2 then
		return true
	end

Line(RayPierced):

        elseif part.Size.Z < 2 and part.Size.X < part.Size.Z and getRelativeNormal(part, normal) == Enum.NormalId.Front or getRelativeNormal(part, normal) == Enum.NormalId.Back then
			cast:SetVelocity(segmentVelocity.Unit * segmentVelocity.Magnitude)
			cast:SetPosition(position)

			print('phaseX')
		elseif part.Size.X < 2 and part.Size.Z < part.Size.X and getRelativeNormal(part, normal) == Enum.NormalId.Left or getRelativeNormal(part, normal) == Enum.NormalId.Right then
			cast:SetVelocity(segmentVelocity.Unit * segmentVelocity.Magnitude)
			cast:SetPosition(position)

			print('phaseZ')
		elseif (part.Size.X == part.Size.Z) and part.Size.X < 2 and part.Size.Z < 2 then
			cast:SetVelocity(segmentVelocity.Unit * segmentVelocity.Magnitude)
			cast:SetPosition(position)

			print('phaseXZ')
		end

getRelativeNormal:

local function getRelativeNormal(hitPart, surfaceNormal)
	local relativeNormal = (hitPart.CFrame - hitPart.Position):Inverse() * surfaceNormal

	if math.abs(relativeNormal.X) >= 0.99 then -- choose by axis
		return math.sign(relativeNormal.X) == 1 -- choose by sign
			and Enum.NormalId.Left
			or Enum.NormalId.Right
	elseif math.abs(relativeNormal.Y) >= 0.99 then
		return math.sign(relativeNormal.Y) == 1
			and Enum.NormalId.Top
			or Enum.NormalId.Bottom
	elseif math.abs(relativeNormal.Z) >= 0.99 then
		return math.sign(relativeNormal.Z) == 1
			and Enum.NormalId.Front
			or Enum.NormalId.Back
	end
	
	return nil
end
1 Like

This doesn’t answer your question, but it might help you:

An easier way to do bullet penetration might be to move forward a bit, raycast backwards (with a whitelist of only the part you hit), and check where the exit point is. Then you can just check the distance between those.

Something like this:

-- returns entry and exit point
local function RaycastEntryExit(origin: Vector3, dir: Vector3, raycastParams: RaycastParams): (Vector3|nil, Vector3|nil)
	local result = workspace:Raycast(origin, dir, raycastParams)
	local exitResult = nil
	if result then
		local hit = result.Instance
		local pos = result.Position
		local ahead = hit.Size.Magnitude
		local exitParams = RaycastParams.new()
		exitParams.FilterType = Enum.RaycastFilterType.Whitelist
		exitParams.FilterDescendantsInstances = {hit}
		exitParams.CollisionGroup = raycastParams.CollisionGroup
		local shortDir = dir.Unit * ahead
		exitResult = workspace:Raycast(pos + shortDir, -shortDir, exitParams)
	end
	return result, exitResult
end

That will

  1. Raycast from a->b
  2. If it hits some part P on the way at point X,
  3. Move forward D amount from the hit point, where D = the maximum dimension of P
  4. Raycast from X + D backwards to get exit point

So in fast cast terms (not sure, just reading the docs) I guess it would be something like

local PEN_AMOUNT = 2 -- studs

local function CanRayPierce(cast, result, segmentVelocity)
	local hit = result.Instance
	local pos = result.Position
	local ahead = hit.Size.Magnitude
	local exitParams = RaycastParams.new()
	exitParams.FilterType = Enum.RaycastFilterType.Whitelist
	exitParams.FilterDescendantsInstances = {hit}
	exitParams.CollisionGroup = raycastParams.CollisionGroup
	local shortDir = dir.Unit * ahead
	local exitResult = workspace:Raycast(pos + shortDir, -shortDir, exitParams)

	return not exitResult or (exitResult.Position-result.Position).Magnitude < PEN_AMOUNT
end
1 Like

Gonna try it out now
30characs

It works but after 2 shots it starts to lag, maybe because
exitParams.FilterType = Enum.RaycastFilterType.Whitelist exitParams.FilterDescendantsInstances = {hit}
are causing this? because it’s hitting bullets too

I’ll try to check if it hits a bullet
Edit:
Ok so I happens when I spammed it, I kinda got it to work so I’ll mark your answer as the solution for now :>

The whitelist makes it faster, not slower, because this way it’s only raycasting for the one part that you hit.

Also

It won’t lag more just because you make more shots. It only runs once, when you hit something.