I’ve been stuck on a coding issue for the past few weeks. One of my commissions focuses on a combat move where the player shoots a beam from their hands. I decided I wanted to add debris around the spot of impact, in other words the raycast position.

What is my issue?
The debris parts rotate on the regular world’s y-axis. Image A

What do I want to achieve?
I want the parts to rotate relative to the pivot*, / I want the parts to be positioned
‘against’ the wall. Image B

What solutions have I tried so far?
I have tried using several methods including CFrame:ToWorldSpace() and such, but I’m not that familiar with 3D spaces, so these failed miserably.

Description (pictures will follow): For this challenge, I have positioned a part named pivot at the position where the ray hits the wall. Image C The pivot is oriented with its front face pointing forward;

--snippet of the pivot creation
local pivot = Instance.new("Part")
pivot.CFrame = CFrame.lookAt(pivot.Position, ray.Position + ray.Normal)

Around the pivot, debris is created;

--snippet of a rock creation including a solution I tried which can be seen in the following images
local rock = Instance.new("Part")
rock.CFrame = pivot.CFrame:ToWorldSpace(CFrame.fromEulerAngles(0, math.rad(angle), 0))
rock.CFrame = rock.CFrame:ToWorldSpace(CFrame.new(0, 0, 5))

It’s not the best code but this is what I was able to make

here’s the code:

local pivot = Instance.new("Part", workspace)
pivot.Anchored = true
pivot.Size = Vector3.new(1, 1, 1)
while true do
local direction = (workspace:WaitForChild("Endpoint").Position - workspace:WaitForChild("origin").Position).Unit
local origin = workspace.origin.Position
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {workspace.origin, workspace.Endpoint, pivot, workspace.circles:GetChildren()}
local result = workspace:Raycast(origin, direction * 1000, params)
if not result then continue end
pivot.CFrame = CFrame.new(result.Position, result.Position + result.Normal) * CFrame.Angles(-math.pi/2, 0, 0)
workspace.circles:ClearAllChildren()
for i = 0, 360, 15 do
local p = Instance.new("Part", workspace.circles)
p.Anchored = true
p.Size = Vector3.new(1, 1, 1)
p.CFrame = pivot.CFrame * CFrame.Angles(0, math.rad(i), 0) * CFrame.new(0, 0, 3)
end
wait(1)
end

This kind of works.
I think I didn’t formulate my question correctly.
How would I create the debris circle that is always relative to the surface it hit? Where it’d always appear like that as in your example even if it hit a wedge.

I don’t know if you ended up getting this working but once you have the placement for the pivot node, you could do multiple raycasts downward relative to the pivots upvector and then place each surrounding rock at each raycast

Unfortunately haven’t fixed it yet.
I already thought of that, but this again falls under my question, how would I go about positioning/raycasting a certain direction relative to the pivot’s UpVector?

Apparently the raycast was being interrupted by a few other parts, I fixed that.
Spawning parts to the pivot’s rightVector while having the pivot rotate around its Z-axis works!