local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {workspace.Ignore}
local p = Pos + Normal * 10
-- If I use CFrame.fromEulerAnglesXYZ(math.rad(0),math.rad(0), math.rad(Angle)) instead of CFrame.Angles(), nothing will change
local Cfr = CFrame.new(Pos)
local Angle = 0
for i = 1,12 do
local Rock = Instance.new("Part")
Rock.Anchored = true
Rock.Size = Vector3.new(1,1,1)
Rock.CFrame = CFrame.new(Pos,p) * CFrame.Angles(math.rad(0),math.rad(0), math.rad(Angle)) * CFrame.new(0, 2, 0)
Rock.Parent = workspace.Ignore
Rock.Material = Material
Angle += 360/i
end
How do I make it perfect? (Pos is the position of the ray, normal is the normal of the ray, the ray touched the wall)
What you are doing is: Angle: 0 i = 1; Angle += 360 → Angle: 360 i = 2; Angle += 180 → Angle: 540 i = 3; Angle += 120 → Angle: 660 i = 4; Angle += 90 → Angle: 750
Etc.
Which is the reason of the weird patern.
Instead what you want is to keep adding the same amount to your value. Angle: 0 i = 1; Angle += 30 → Angle: 30 i = 2; Angle += 30 → Angle: 60 i = 3; Angle += 30 → Angle: 90 i = 4; Angle += 30 → Angle: 120
Etc. Note that 360 / 12 = 30.
So what you want to do instead is something like this:
local i_max = 12
for i = 1, i_max do
... -- inital code
Angle += (360 / i_max)
end
The white block is the place where ray hit, but as you can see, the blocks of the wall slam effect are planks even on the side of grass, so I want to make blocks get the material and color of the place where they are located, I guess raycasting is a solution here:
local ray = workspace:Raycast(Rock.CFrame.p,???,rayParameters)
I think CFrame.lookVector doesn’t work here, so I need an alternative.
Can you help me find out what should I write instead of “???”, so the rocks will get their material, also make it so it will work on any direction the ray hit? ( I mean it will work no matter what direction the origin of the first ray was facing: Left, Right, Forward, Back)
An easier way would be to get the touching parts, which are not the slamParts.
First we would need to name every part something or add an attribute so we know what to ignore.
Rock.Name = "SlamPart"
After that, we can use :GetTouchingParts(), though this will not get great results if there are more than 2 parts touching the current part, so I suggest only doing this with parts which are only Touching 1 part which is not a slamPart nor we want any player’s avatar or skin to get the same texture:
local TouchingParts = Rock:GetTouchingParts()
-- if we use table.remove() and we go from 1 to max and we would remove 1 then the for in pairs loop would not update
-- so instead this is my solution instead of remembering how many parts we removed from the table
for i = #TouchingParts, 1 do
if not TouchingParts[i] or TouchingParts[i].Name == "SlamPart" or TouchingParts[i].Parent:FindFirstChildWhichIsA("Humanoid") then
table.remove(TouchingParts, i)
end
end
if #TouchingParts == 1 then
Rock.Material = TouchingParts[1].Material
Rock.Color = TouchingParts[1].Material
else -- if 0 Touching parts or >1 then
... -- use raycast in this case, due to it being on an edge or some sorts
-- else you could just make it the hit ray's Material if there is a TouchingPart which is the same
end
This is a solution for the problem you are facing currently, though this won’t last for long.
I am trying to avoid using raycasts as I myself am pretty horrible with it, due to the fact there are many ways to handle raycasts and I can’t find the best one or at least when which is suited.
I’ve tested it and it’s pretty buggy, rocks hit each other and get their materials, even though we remove their index from the table, can you offer some less buggy version? It only bugs if I stand to the crater close, if I create it from far it doesn’t bug. I guess it’s because there are too many objects in a table(more than 2), so removing by index is a bad idea, the values move and next time you remove by index, you can remove not the object you wanted to.