How to make proper wallbanging?

I have spent 5 hours trying to get a good answer from ChatGPT, still nothing. What i want is to get the amount of studs that a raycast intersects with a certain part. Like shooting down on a part while standing on it will make the amount of studs intersected the same as the part’s height. But if I stand in front of the part, aim down almost to the ground but still looking at the part, it should be just a little amount of studs, probably less than 1 on a standard 4x2x2 part. I tried raycasting normally, getting its .Position, and raycasting from that position with the same direction to get the other side, to then calculate the distance, but the 2nd raycast returns nil. Then since wallbanging a wall just for the bullet to hit nothing is useless, i tried to, after collecting all the parts the 1st raycast hits, take the part that got hit after the current one, and raycast from part with the direction reversed, which also didn’t work well. I’m probably just doing the reverse of it wrong. So 2 questions:

  1. How do you properly make this?
  2. How do you reverse a (unit vector) direction so that, for example cast A with direction A will intersect at the center with cast B with direction (A but reversed)?

can you sent the script for the raycast idea?

to get the reversed direction of a ray you just need to negate it like you would with any vector3. eg.

local x = Vector3.new(1, 2, 3)
local reversed = -x --> -1, -2, -3

to calculate the number of studs a raycast intersects with a part:

  1. perform the initial raycast and store the hit position
  2. choose a point far away in the direction of the raycast (e.g., 300 studs forward)
  3. perform a second raycast from this point back towards the hit position by inverting the direction of the first raycast (use a whitelist for this one, include only the object that u hit)
  4. calculate the distance between the two hit positions
  5. subtract this distance from a “wallbang power” variable and repeat until the variable reaches 0 or a maximum number of objects is penetrated

now you should get the desired intersection measurement regardless of the angle of the raycast

1 Like

like this? Modeling a projectile's motion - #10 by EgoMoose

This is correct. Though I would add that the reverse ray should be created with a whitelist where only the part you are checking can be hit by the raycast.

I had the same idea. Although you can probably use the 3D diagonal of the part as the distance ahead for the retrograde raycast’s origin instead of a constant like 300. The only problem is if you have a concave mesh that has two separate intersections that’ll either misreport the thickness or skip anything inside if the next raycast starts from the exit point. I’m not sure how common concave meshes are in a shooter though.

that is quite the interesting edge case. i didn’t even consider the use of 3D diagonals.
how would one go about using that rather than multiple raycasts

It isn’t a method that uses less raycasts than what you’ve provided, I just mean that the diagonal of a part’s size is the largest distance possible inside of it. The distance of the raycast that goes back to find the suspected exit point shouldn’t need to move ahead further than that extent.

So, 20 minutes of trying to do it myself led me to

local character = game.Players.LocalPlayer.Character
		local head = character:FindFirstChild("Head")
		local camera = workspace.CurrentCamera
		local origin = head.Position
		local direction = camera.CFrame.LookVector
		local found = true
		local parts = {}
		local rp = RaycastParams.new()
		rp.FilterDescendantsInstances = {workspace.CurrentCamera, game.Players.LocalPlayer.Character}
		rp.FilterType = Enum.RaycastFilterType.Exclude
		local iter = 0
		while found do
			local r = workspace:Raycast(origin, direction * 512, rp)
			if r then
				table.insert(parts, {r.Instance, r.Position})
				origin = r.Position + direction * .01
			else
				found = false
				break
			end
			iter += 1
			if iter > 100 then
				break
			end
		end
		local totalPenetration = 0
		for i,v in pairs(parts) do
			if i ~= #parts then
				local rp2 = RaycastParams.new()
				rp2.FilterType = Enum.RaycastFilterType.Include
				rp2.FilterDescendantsInstances = {v[1]}
				local raycastB = workspace:Raycast(parts[i + 1][2], -direction * 512, rp2)
				if raycastB then
					local magn = (parts[i + 1][2] - v[2]).Magnitude
					totalPenetration += magn
				else
					print("No raycast result on index ", i)
				end
			end
		end
		print("Total:",totalPenetration)

It only works if there’s another part (or the raycast hit another part of the same mesh) that the raycast hit after the part you’re trying to get intersection of, but if it doesn’t hit any other part, i don’t need to know the penetration since it’s useless

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