Problem with rotation of part in viewport frame

when i point my camera upwards my vpf_arrow in the viewport frame points downwards, i want the arrow to point upwards as well in the viewport; the arrow above my head is doing that correctly but not in the viewport. im super confused about rotation and stuff so id really love some help ty!!!

local p = game.Players.LocalPlayer
local c = p.Character or p.CharacterAdded:Wait()
local playergui = p.PlayerGui
local arrowui = playergui:WaitForChild("arrowUI")
local vpf = arrowui:WaitForChild("arrow_vpf")
local hrp = c.PrimaryPart
local h = c:WaitForChild("Humanoid")
local rs = game:GetService("RunService")
local cam = workspace.Camera
local cam_atarrow = false
local arrow = game.ReplicatedStorage:WaitForChild("arrow")
local connection = nil

local newarrow = arrow:Clone()
newarrow.Parent = workspace
newarrow.CanCollide = false
local clickdetector = newarrow:WaitForChild("ClickDetector")
local vpf_arrow = newarrow:Clone()
local vpf_cam = Instance.new("Camera")
vpf_arrow.ClickDetector:Destroy()
vpf_arrow.CFrame = CFrame.new(0,0,0)
vpf_cam.CFrame = CFrame.new(0,0,10)
vpf_arrow.Parent = vpf
vpf.CurrentCamera = vpf_cam
vpf.Visible = true

connection = rs.RenderStepped:Connect(function(deltatime)
	--one way to color these guys:
	local x,y,z = math.abs(cam.CFrame.LookVector.X), math.abs(cam.CFrame.LookVector.Y), math.abs(cam.CFrame.LookVector.Z)
	local red = Color3.new(1, 0.172549, 0.172549)
	local green = Color3.new(0.435294, 1, 0.396078)
	local blue = Color3.new(0.282353, 0.258824, 1)
	local total = x + y + z
	local xweight = x / total
	local yweight = y / total
	local zweight = z / total
	local interpolatedcolor = Color3.new(
		(red.R * xweight) + (green.R * yweight) + (blue.R * zweight),
		(red.G * xweight) + (green.G * yweight) + (blue.G * zweight),
		(red.B * xweight) + (green.B * yweight) + (blue.B * zweight)
	)
	newarrow.Color = interpolatedcolor
	local arrow_pos = c:WaitForChild("Head").Position + Vector3.new(0, 3, 0)
	newarrow.CFrame = CFrame.new(arrow_pos, arrow_pos + cam.CFrame.LookVector) * CFrame.Angles(math.rad(-90),0,math.rad(0))
	vpf_arrow.Color = newarrow.Color
	vpf_arrow.CFrame = CFrame.new(vpf_arrow.Position, vpf_arrow.Position + cam.CFrame.LookVector) * CFrame.Angles(math.rad(90),0,math.rad(0))
end)

we can make it cleaner by setting them in separate functions also the viewport arrow rotation rn is corrected we can just inverting the y compnent of the lock vector

local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Data = {
    Player = {
        Instance = game.Players.LocalPlayer,
        Character = nil,
        GUI = nil
    },
    Arrow = {
        Model = ReplicatedStorage:WaitForChild("arrow"),
        World = nil,
        Viewport = nil
    },
    UI = {
        ArrowUI = nil,
        Viewport = nil
    },
    Camera = workspace.Camera
}

local function setupCharacter()
    Data.Player.Character = Data.Player.Instance.Character or Data.Player.Instance.CharacterAdded:Wait()
    Data.Player.GUI = Data.Player.Instance.PlayerGui
    Data.UI.ArrowUI = Data.Player.GUI:WaitForChild("arrowUI")
    Data.UI.Viewport = Data.UI.ArrowUI:WaitForChild("arrow_vpf")
end

local function setupArrows()
    Data.Arrow.World = Data.Arrow.Model:Clone()
    Data.Arrow.World.Parent = workspace
    Data.Arrow.World.CanCollide = false

    Data.Arrow.Viewport = Data.Arrow.World:Clone()
    Data.Arrow.Viewport.ClickDetector:Destroy()
    Data.Arrow.Viewport.CFrame = CFrame.new()
    Data.Arrow.Viewport.Parent = Data.UI.Viewport
end

local function setupViewport()
    local vpfCamera = Instance.new("Camera")
    vpfCamera.CFrame = CFrame.new(0, 0, 10)
    Data.UI.Viewport.CurrentCamera = vpfCamera
    Data.UI.Viewport.Visible = true
end

local function interpolateColor(lookVector)
    local absVector = lookVector:Abs()
    local colors = {
        Color3.new(1, 0.172549, 0.172549),
        Color3.new(0.435294, 1, 0.396078),
        Color3.new(0.282353, 0.258824, 1)
    }
    local total = absVector.X + absVector.Y + absVector.Z
    local weights = absVector / total
    return Color3.new(
        colors[1].R * weights.X + colors[2].R * weights.Y + colors[3].R * weights.Z,
        colors[1].G * weights.X + colors[2].G * weights.Y + colors[3].G * weights.Z,
        colors[1].B * weights.X + colors[2].B * weights.Y + colors[3].B * weights.Z
    )
end

local function updateArrows()
    local lookVector = Data.Camera.CFrame.LookVector
    local arrowColor = interpolateColor(lookVector)
    
    local headPosition = Data.Player.Character.Head.Position
    local arrowPosition = headPosition + Vector3.new(0, 3, 0)
    
    Data.Arrow.World.Color = arrowColor
    Data.Arrow.World.CFrame = CFrame.new(arrowPosition, arrowPosition + lookVector) * CFrame.Angles(math.rad(-90), 0, 0)
    
    Data.Arrow.Viewport.Color = arrowColor
    local vpfLookVector = Vector3.new(lookVector.X, -lookVector.Y, lookVector.Z)
    Data.Arrow.Viewport.CFrame = CFrame.lookAt(Vector3.new(), vpfLookVector) * CFrame.Angles(math.rad(90), 0, 0)
end

setupCharacter()
setupArrows()
setupViewport()

RunService.RenderStepped:Connect(updateArrows)
1 Like

you absolute legend. i wouldnt have figured it out in a thousand years man. thanks a million for re-organising my script and for solving my problem. have a great day bro!!!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.