[Solved] How to keep block in front of player's face aligned on all 3 axis (Head CFrame doesn't work)

Just off the top, attaching anything to the Head’s CFrame doesn’t work for 2 reasons:

  1. it only positions the block correctly on the X and Z axis,
  2. the block moves with player idle animation (undesirable for game)

I have a block that needs to stay in front of the player’s camera at a given distance, only when the player is in first person view.

-- LocalScript
-- gets and transmits the position and direction of the first person camera
local camera = workspace.CurrentCamera
local viewportPoint = camera.ViewportSize / 2 -- gets the center of the camera view
local unitRay

while wait(.1) do
  unitRay = camera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y, 0)
  pos = unitRay.Origin
  dir = unitRay.Direction
  game.ReplicatedStorage.XmitPos:FireServer(pos,dir)
end

This is the closest I can get:

-- Script on block that is to be in front of player's view

game.ReplicatedStorage.XmitPos.OnServerEvent:Connect(function(player,pos,dir)
	script.Parent.CFrame = CFrame.new(pos) * CFrame.new(0,0,-5) * CFrame.Angles(dir.X, dir.Y, dir.Z)
end)

It positions correctly on the Z axis:


When the player camera rotates on any axis, block stays 5 studs away on the Z axis. The cube rotates on its own axis though.
RobloxScreenShot20220813_151743876

Thank you!!

Why can’t you use welds? That will probably be easiest, no? You can clean them up when needed as well.

local Game = game
local Workspace = workspace
local RunService = Game:GetService("RunService")
local Players = Game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Head = Character:WaitForChild("Head")
local Camera = Workspace.CurrentCamera
local Part = Instance.new("Part")
Part.Parent = Workspace

local function OnRenderStep()
	local Distance = (Head.Position - Camera.CFrame.Position).Magnitude
	if Distance > 1 then return end
	Part.CFrame = Head.CFrame * CFrame.new(0, 0, -5)
end

RunService.RenderStepped:Connect(OnRenderStep)

This works.

Thanks for this cool idea. I made a part that stays in the center of the viewport, then welded the target to it. This is the script on the part that stays on the player’s viewport:

game.ReplicatedStorage.XmitPos.OnServerEvent:Connect(function(player,pos,dir)
	script.Parent.CFrame = CFrame.new(pos) * CFrame.Angles(dir.X, dir.Y, dir.Z)
end)

However, the target block moves in a strange way that I can’t figure out. It looks like the axis are switched, but not totally. Any guess why?

robloxapp-20220813-1915328

scanner_distance_test.rbxl (37.3 KB)

Hello and thanks! Your solution does indeed place a block at a fixed distance in front of the player. A couple of issues with this method (mentioned in my first post but could have been more clear):

  1. it only positions the block on the X and Z axis
  2. the block moves along with idle animation (undesirable for game)

Any thoughts on how to get the block to move on the Y axis as well? Ie if a player is looking up, the block will move up along with the viewport?

Thanks!!

Figured it out :face_exhaling: With ViewportPointToRay you can specify an offset distance. Didn’t realize I could use that point to place an object! For best result transmit the position/direction on something better than a wait(.1) timer.

-- LocalScript
-- Tells game where player's viewport is, and were to place the targeted object

local camera = workspace.CurrentCamera
local viewportPoint = camera.ViewportSize / 2
local unitRay

while wait(.1) do
	unitRay = camera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y, 5)
	pos = unitRay.Origin
	dir = unitRay.Direction
	game.ReplicatedStorage.XmitPos:FireServer(pos,dir)
end
-- Script that goes on object you'd like to keep away from player's viewport

game.ReplicatedStorage.XmitPos.OnServerEvent:Connect(function(player,pos,dir)
	script.Parent.CFrame = CFrame.new(pos) * CFrame.Angles(dir.Y, -dir.X, dir.Z)
end)