Okay, so I have this placement system that works almost flawlessly on horizontal and unrotated surfaces, but if the surface is either verticle or diagonal (rotated), problems arise.
local e = false
local tb = Instance.new("Model")
local tbb = Instance.new("Part",tb)
tb.PrimaryPart=tbb
tbb.Anchored=true
local mou = game.Players.LocalPlayer:GetMouse()
game:GetService("RunService").RenderStepped:Connect(function()
local rcp = RaycastParams.new()
rcp.FilterType=Enum.RaycastFilterType.Blacklist
rcp.FilterDescendantsInstances={game.Players.LocalPlayer.Character,tb}
local ray = workspace:Raycast(workspace.CurrentCamera.CFrame.Position,(mou.Hit.p-workspace.CurrentCamera.CFrame.Position).Unit*500,rcp)
if ray==nil then
tb.Parent=nil
else
tb.Parent=workspace
local i1 = Vector3.new(ray.Position.X,ray.Position.Y,ray.Position.Z)+ray.Normal.Unit*(tb.PrimaryPart.Size/Vector3.new(2,2,2))
local intended = CFrame.new(i1)
local p1 = intended.Position+intended.LookVector.Unit*(tb.PrimaryPart.Size.Z/2)+intended.UpVector.Unit*(tb.PrimaryPart.Size.Y/2)+intended.RightVector.Unit*(tb.PrimaryPart.Size.X/2)
local p2 = intended.Position-intended.LookVector.Unit*(tb.PrimaryPart.Size.Z/2)-intended.UpVector.Unit*(tb.PrimaryPart.Size.Y/2)-intended.RightVector.Unit*(tb.PrimaryPart.Size.X/2)
print(Vector3.new(math.abs(p1.X-p2.X),math.abs(p1.Y-p2.Y),math.abs(p1.Z-p2.Z)))
print(intended.Position)
print(ray.Instance.Position.X-ray.Instance.Size.X/2+math.abs(p1.X-p2.X)/2)
print(ray.Instance.Position.X+ray.Instance.Size.X/2-math.abs(p1.X-p2.X)/2)
print(ray.Instance.Position.Z-ray.Instance.Size.Z/2+math.abs(p1.Z-p2.Z)/2)
print(ray.Instance.Position.Z+ray.Instance.Size.Z/2-math.abs(p1.Z-p2.Z)/2)
print(math.clamp(intended.Position.X,ray.Instance.Position.X-ray.Instance.Size.X/2+math.abs(p1.X-p2.X)/2,ray.Instance.Position.X+ray.Instance.Size.X/2-math.abs(p1.X-p2.X)/2))
local intended2
if math.abs(ray.Normal.Unit.Y)==1 then
intended2 = CFrame.new(Vector3.new(math.clamp(intended.Position.X,ray.Instance.Position.X-ray.Instance.Size.X/2+math.abs(p1.X-p2.X)/2,ray.Instance.Position.X+ray.Instance.Size.X/2-math.abs(p1.X-p2.X)/2),intended.Position.Y,math.clamp(intended.Position.Z,ray.Instance.Position.Z-ray.Instance.Size.Z/2+math.abs(p1.Z-p2.Z)/2,ray.Instance.Position.Z+ray.Instance.Size.Z/2-math.abs(p1.Z-p2.Z)/2)))
elseif math.abs(ray.Normal.Unit.X)==1 then
intended2 = CFrame.new(Vector3.new(intended.Position.X,math.clamp(intended.Position.Y,ray.Instance.Position.Y-ray.Instance.Size.Y/2+math.abs(p1.Y-p2.Y)/2,ray.Instance.Position.Y+ray.Instance.Size.Y/2-math.abs(p1.Y-p2.Y)/2),math.clamp(intended.Position.Z,ray.Instance.Position.Z-ray.Instance.Size.Z/2+math.abs(p1.Z-p2.Z)/2,ray.Instance.Position.Z+ray.Instance.Size.Z/2-math.abs(p1.Z-p2.Z)/2)))
elseif math.abs(ray.Normal.Unit.Z)==1 then
intended2 = CFrame.new(Vector3.new(math.clamp(intended.Position.X,ray.Instance.Position.X-ray.Instance.Size.X/2+math.abs(p1.X-p2.X)/2,ray.Instance.Position.X+ray.Instance.Size.X/2-math.abs(p1.X-p2.X)/2),math.clamp(intended.Position.Y,ray.Instance.Position.Y-ray.Instance.Size.Y/2+math.abs(p1.Y-p2.Y)/2,ray.Instance.Position.Y+ray.Instance.Size.Y/2-math.abs(p1.Y-p2.Y)/2),intended.Position.Z))
else
intended2=intended
end
local r = 45
intended2=intended2*CFrame.fromEulerAnglesXYZ(math.rad(ray.Instance.Orientation.X),math.rad(ray.Instance.Orientation.Y),math.rad(ray.Instance.Orientation.Z))
game:GetService("TweenService"):Create(tb.PrimaryPart,TweenInfo.new(.1/3,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{CFrame=intended2}):Play()
end
end)
The first problem is that I have no idea how to make surface normal boundaries/clamping for rotated surfaces, both horizontal and vertical.
The second problem is that my part’s front/back face is always parallel to the surface’s front/back face, and my part’s right/left face is always parallel to the surface’s right/left face, and vice versa.
Instead, I want my part’s front face to always be facing the surface normal touching the part IF THE SURFACE NORMAL IS VERTICAL, NOT HORIZONTAL. , like so
The third problem is that the distance between the surface normal touching the part, to the part, is incorrectly calculated if the surface is diagonal or vertical.
If you still don’t understand, here’s a video of me displaying all the problems I mentioned above.
I don’t want hacky or downright terrible solutions. I want a solution that’s efficient, loyal to the initial code, and works 100% of the time. I don’t want copy and pasted code either. I want a thorough explanation, so in the future I can look back and make more of these placement scripts from memory.