Part Orientation Help

So I’ve made a fully functional spray paint bottle where the paint decal orientates to the surface it was sprayed on (surface normals). But now, I’m trying to make the part face toward you if its surface normal is (0, 1, 0), aka a flat surface pointing at the sky.

I’ve experimented so far by just subtracting the root part’s orientation by 90 degrees (since that was the part’s orientation relative to the root when I tested), but it only works if your root is orientated closer to 0 or -180 degrees, like this:

It doesn’t work when your root is rotated closer to 90 or -90 degrees (it’s flipped):

I’m also stuck with multiples of 90, I can’t seem to get it to look right with any other orientations in between.

How do I get it to orientate perfectly to where my character is looking, so I can get diagonal rotations, too?

Relevant Client Code:

mouse.Button1Down:Connect(function()
	if not equipped or cooldown or not canSpray or rolling.Value or not humanoid.AutoRotate or humanoid:GetState() == Enum.HumanoidStateType.Swimming then return end 
	
	local ray = Ray.new(camera.CFrame.p, camera.CFrame.LookVector * 40)
	
	local hit, pos, normal = workspace:FindPartOnRayWithIgnoreList(ray, {char})
	
	if hit then 
		if hit.Transparency >= 1 then return end 
		
		sprayAnim:Play()
		spraySound:Play()
		
		sprayEvent:FireServer(pos, normal)
		cooldown = true
		wait(3.5)
		cooldown = false
	end
end)

Relevant server code (connected to a RemoteEvent):

sprayEvent.OnServerEvent:Connect(function(player, pos, normal)
	if not player then return end 	
	
	local clone = paintPart:Clone()
	
	clone.CFrame = CFrame.new(pos, pos + normal)
	
	--print(normal)
	--print("Clone:", clone.Orientation)
	
	if normal == Vector3.new(0, 1, 0) then -- orientate the part to look towards you
		local char = player.Character or player.CharacterAdded:Wait()
		local root = char:FindFirstChild("HumanoidRootPart")
		
		if root then 
			print(root.Orientation.Y)
			clone.CFrame = clone.CFrame * CFrame.Angles(0, 0, math.rad(root.Orientation.Y - 90))
		end
	end
1 Like

You could try something like this:

function YAxisLookAt(originalPos, lookAtPos) 
return CFrame.new(originalPos, Vector3.new(lookAtPos.X, originalPos.Y, lookAtPos.z)) 
end

Clone.CFrame = YAxisLookAt(pos, pos + normal)

This code would allow you to have the part face the direction of the normal on only the Y axis, while leaving the others alone.

Pretty sure that wouldn’t work and would cause the part’s front face to look at the position which would cause it to clip through the ground somewhat like this:

image

Anyways, I fixed it, I was on the right track with my experiments. Simply adding the orientations of the root part and the paint decal part and then negating it worked:

clone.CFrame = clone.CFrame * CFrame.Angles(0, 0, -math.rad(root.Orientation.Y + clone.Orientation.Y))
1 Like