How would I go around with an aiming line for guns in a top-down game?

Hi! I’m trying to plan out a way for me to make a GUI that shows the aiming line of a gun similar to the one in Running with Rifles and Foxhole…

If you were to look in the image, the white line represents the aiming line that the bullet will follow, and the length of the line will be limited if blocked by an obstacle.

I believe it has to do something with raycasting if implemented in ROBLOX, but I would like other thoughts on this since I’m lacking a bit in experience. Thanks!

I’m quite curious too. Honestly, the way I’d do it is with raycasting.

When you cast a ray, it comes with a hit detector that will tell the position of where the ray hit (if it hits something). Now that you have the two points, I’d have 1 part that would be positioned over the ray, constantly changing relative to the distance between the two points. Probably use heartbeat() or something like that to smoothly change the part’s size.

Just throwing my idea out. Hope it helps.

1 Like

Good idea! I tried your idea via a raycast plus beam with this very crude script I made… it works but it has an issue where the target starts locking onto a ‘part’ that exists, so its location is determined by the midpoint of a brick that it hits.

Here’s a script I made:

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local RS = game:GetService("RunService")
local TOOL = script.Parent

	local part ="Part")
	part.Parent = workspace
	part.Name = "Aim"
	part.Size =, 0.1, 0.1)
	part.Transparency = 1
	part.Anchored = true
	mouse.TargetFilter = part
	local focus ="Part")
	local attachment ="Attachment")
	attachment.Parent = focus
	local beam ="Beam")
	beam.Parent = TOOL
	beam.Attachment0 = focus.Attachment
	beam.Attachment1 = TOOL.Flare.Attachment
	beam.Width0 = 0.2
	beam.Width1 = 0.2
	beam.FaceCamera = true
	beam.Transparency =,0.2)
	focus.Parent = workspace
	focus.Name = "AimFocus"
	focus.Anchored = true
	focus.BrickColor ="Really red")
	focus.CanCollide = false
	focus.Size =, 0.1, 0.1)
	while RS.Heartbeat:Wait() do
		part.CFrame =
		local rayOrigin = script.Parent.Flare.Position
		local rayDestination = part.Position
		local rayDirection = rayDestination - rayOrigin

		local ray =, rayDirection)
		local PART = workspace:FindPartOnRay(ray)
		focus.Position = PART.Position

	local part = workspace:FindFirstChild("Aim")
	local part2 = workspace:FindFirstChild("AimFocus")
	local beam = TOOL:FindFirstChild("Beam")

When not obstructed:

When obstructed:
Notice how the beam doesn’t focus to the cursor.

I’ve found the issue, because the FindPartOnRay will find bricks and my script will make the Focus part’s position the same as the obstacle’s position. However I’m not sure how to go around this.
I hope someone can help me with this issue, thanks!

Ah, FindPartOnRay wasn’t the thing I’m talking about. There’s another thing you can do with rays, which is raycastResult.Position. Here’s a snippet of code that I use for my own gun system, modified slightly.

local raycastResult = workspace:Raycast(barrel.Position, unitRay.Direction * 1000)
if raycastResult then
     -- prints where the ray hit exactly 

which should give you the exact location of where the ray hit, instead of snapping onto the part where you hit. I noticed that you’re using instead of workspace:Raycast() which I don’t know which is better, but I think it’s the newer way to raycast. Here’s an overview of the most up-to-date way to raycast (I think) and raycast.Position should be included here.

1 Like

Ooh, I see, I’ll read a bit on Raycasting and thanks for the reply on the raycastResult.Position. I’ve tweaked it to my needs and while it is better than before, there’s an issue where the raycastResult.Position keeps approaching the player when raycastResult = true.


After some time:

The adjustment I did:

while RS.Heartbeat:Wait() do
		part.CFrame =
		local rayOrigin = script.Parent.Flare.Position
		local rayDestination = part.Position
		local rayDirection = rayDestination - rayOrigin

		local raycastResult = workspace:Raycast(rayOrigin, rayDirection)
		focus.Position = raycastResult.Position

Nevermind, I found the issue:

The focus part wasn’t filtered and so the raycastResult had its ‘part’ on the focuspart which was causing the issue.

For anyone who reads this, the script I added is:

local raycastParams =
	raycastParams.FilterDescendantsInstances = {focus}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
1 Like

Glad to help! If everything is fine now please mark a solution.

1 Like