What I’m trying to do is to make a FPS crosshair, something similar to this
However I’m not sure what approach to use, my first idea was to use an ImageFrame with the lines, however I have heard of manually making the crosshair lines.
Now if I were to use the ImageFrame method, how would I calculate a Vector3 Unit direction within the frame accounting for the Client’s resolution / viewport size etc. Additionally how would doing something like making the Frame size increase when the gun is fired, and decrease it’s size when not firing?
Some ideas, maybe connect it to MouseButton1Click and increase the size with a Tween. Maybe also make it a ModuleScript to have a function that needs a gunShot value. All just ideas.
You could for one use UI Size Contraints to for sure lock it in the center of the screen, and then use multiple separate frames for each bit of the crosshair.
After this, you use events (i.e whenever they’re crouching, aiming in, etc) to tween the crosshairs to their corrosponding positions.
You need to position 4 frames (the hairs or whatever the name of those things are) in an origin position (in this case, the screen center, which you can get by doing AbsoluteSize on a ScreenGui and dividing it by 2) and move them a few pixels away from ut (offset from the origin)
To do this, you just have to do: Frame.Position = OriginPoint + Offset for each of them; both OriginPoint and Offset must be UDim2
For the right and left frames, the offset would only contain only X values and for the top and bottom it would contain Y values
This is some code I could come up with in my spare time
Remember to disable ScreenGui.IgnoreGuiInset
-- Variables
local screenGui = script.Parent
local resolution = screenGui.AbsoluteSize
local origin = UDim2.fromOffset(resolution.X / 2, resolution.Y / 2)
local radius = 15 -- This is our offset number in pixels, we use this to 'move' the frames from our origin
local hairs = {}
-- Settings
-- Size of the frames
local FRAME_X = 5
local FRAME_Y = 1
-- Logic
local function newFrame(): Frame
local frame = Instance.new("Frame") -- If you wanted to make something like a shotgun crosshair, you'd probably need a ImageLabel instead
frame.Name = "_hair"
frame.Parent = screenGui
frame.Size = UDim2.fromOffset(FRAME_X, FRAME_Y)
frame.AnchorPoint = Vector2.new(0.5, 0.5)
-- Add extra settings here if you want
return frame
end
local function updateCrosshair()
local verticalOffset, horizontalOffset = UDim2.fromOffset(0, radius), UDim2.fromOffset(radius, 0)
hairs.top.Position = origin + -verticalOffset
hairs.bottom.Position = origin + verticalOffset
hairs.right.Position = origin + -horizontalOffset
hairs.left.Position = origin + horizontalOffset
end
local function main()
local top, bottom, right, left = newFrame(), newFrame(), newFrame(), newFrame()
-- This is the bottom and top frames so we have to make them thinner in width and larger in height
top.Size = UDim2.fromOffset(FRAME_Y, FRAME_X)
bottom.Size = UDim2.fromOffset(FRAME_Y, FRAME_X)
hairs = {
top = top,
bottom = bottom,
right = right,
left = left
}
-- Constantly update crosshair
-- You could probably bind it to an event that fires whenever the radius changes instead
while true do
updateCrosshair()
--radius = math.abs(math.cos(os.clock())) * 25 -- Testing purposes
task.wait()
end
end
main()