How can I make this Block, which is always supposed to face opposite to the Camera, more accurate?

As the title suggest, I want a Block which will always be 20 Studs away from my Head, to essentially be facing opposite to my Camera’s Position.

The reason for this, is to create a System similar to Blade Ball 's Curve Mechanic based on where the Player is looking. I plan on replicating this using Attachments in the block and AlignPosition | Documentation - Roblox Creator Hub, example: Watch BladeBallMimic | Streamable . (Including this incase someone can recommend a better method than this “Camera Block” method)

What I currently have seems to work well for the X and Z direction, however for the Y direction (Up and Down), sometimes it works, sometimes it does not, and I’m not sure why.

External Media

I have the following Code in a LocalScript

-- SERVICES
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- VARIABLES
local Camera = workspace.CurrentCamera

while true do

	local X, Y, Z = Camera.CFrame:ToEulerAnglesXYZ()
	ReplicatedStorage.Look:FireServer(X, Y, Z)
	
	task.wait()
end

And then the following in a ServerScript

-- SERVICES
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Players.PlayerAdded:Connect(function(Player: Player)
	
	Player.CharacterAdded:Connect(function(Character: Model)
		
		local Head = Character.Head
		local HumanoidRootPart = Character.HumanoidRootPart
		
		-- Looker [WHAT CONTROLS BLOCK USING WELD ROTATIONS]
		local Looker = Instance.new("Part")
		Looker.Name = "Looker"
		Looker.Parent = Head
		Looker.Size = Vector3.one
		Looker.CanCollide = false
		Looker.Massless = true
		Looker.Transparency = 1
		Looker.CFrame = Head.CFrame
		
		-- To adjust for Head moving
		local Rotator1 = Instance.new("Weld")
		Rotator1.Name = "Rotator1"
		Rotator1.Parent = Looker
		Rotator1.Part0 = Head
		Rotator1.Part1 = Looker
		
		-- Hitter Block [BLOCK VISUALIZATION]
		local HitterBlock = Instance.new("Part")
		HitterBlock.Name = "HitterBlock"
		HitterBlock.Parent = Looker
		HitterBlock.Size = Vector3.new(5, 5, 5)
		HitterBlock.CanCollide = false
		HitterBlock.Massless = true
		HitterBlock.Transparency = 0.5
		HitterBlock.Color = Color3.fromRGB(0, 255, 0)
		
		-- This controls the Block linked with the Camera
		local Rotator2 = Instance.new("Weld")
		Rotator2.Name = "Rotator2"
		Rotator2.Parent = HitterBlock
		Rotator2.Part0 = HitterBlock
		Rotator2.Part1 = Looker
		Rotator2.C0 = CFrame.new(0, 0, 20)
		
		local Hitter = Instance.new("Attachment")
		Hitter.Name = "Hitter"
		Hitter.Parent = HitterBlock
		Hitter.Visible = true
	end)
end)

ReplicatedStorage.Look.OnServerEvent:Connect(function(Player: Player, X: number, Y: number, Z: number)

	local Head = Player.Character:WaitForChild("Head")
	local HitterBlock = Head.Looker.HitterBlock
	
	local Rotator1 = Head.Looker.Rotator1
	local Rotator2 = HitterBlock.Rotator2
	
	-- To account for Head Moving around
	local XX = math.rad(Head.Orientation.X)
	local YY = math.rad(Head.Orientation.Y)
	local ZZ = math.rad(Head.Orientation.Z)
	
	Rotator1.C1 = CFrame.Angles(XX, YY, ZZ)
	Rotator2.C0 = CFrame.new(0, 0, 20) * CFrame.Angles(-X, -Y, Z)
end)

Both are connected using an UnreliableRemoteEvent | Documentation - Roblox Creator Hub, and Rotation is done by adjusting the Weld’s Properties. below is the File with all of the above to Test for yourself.

Looker.rbxl (54.9 KB)

All help or ideas appreciated, thank you!

Answered by @Gosaiknight01 in a Discord server, huge thanks to them :pray:

Instead of using Weld’s, we can just use the Camera’s LookVector:

LocalScript

-- SERVICES
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- VARIABLES
local Camera = workspace.CurrentCamera

while true do

	local LookVector = Camera.CFrame.LookVector
	ReplicatedStorage.Look:FireServer(LookVector)

	task.wait()
end

ServerScript

-- SERVICES
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Players.PlayerAdded:Connect(function(Player: Player)

	Player.CharacterAdded:Connect(function(Character: Model)

		local Head = Character.Head
		local HumanoidRootPart = Character.HumanoidRootPart

		-- Hitter Block [BLOCK VISUALIZATION]
		local HitterBlock = Instance.new("Part")
		HitterBlock.Name = "HitterBlock"
		HitterBlock.Parent = Head
		HitterBlock.Size = Vector3.new(5, 5, 5)
		HitterBlock.CanCollide = false
		HitterBlock.Massless = true
		HitterBlock.Transparency = 0.5
		HitterBlock.Color = Color3.fromRGB(0, 255, 0)
		HitterBlock.Anchored = true
	end)
end)

ReplicatedStorage.Look.OnServerEvent:Connect(function(Player: Player, LookVector: CFrame)

	local Head = Player.Character:WaitForChild("Head")
	local HitterBlock = Head.HitterBlock

	HitterBlock.CFrame = Head.CFrame + (LookVector * 20)
end)

Looker.rbxl (54.4 KB)