Raycast only reliably hits one side of parts

I’m very new to raycasting, so sorry if this is a simple answer but I can’t seem to find anything online about it. I’ve created a tool that fires multiple raycasts and when they hit a part they clone another part with a decal on it from replicated storage. The problem is that the rays only seem to hit one specific side of the parts, although rarely they will hit the backside (see below).

local laser = script.Parent
local rs = game:GetService("RunService")
local uis = game:GetService("UserInputService")
local radius = 0.1
local testpart = game:GetService("ReplicatedStorage"):WaitForChild("Testpart")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character
if not character or not character.Parent then
	character = player.CharacterAdded:wait()
end
local head = character:WaitForChild("Head")
player.CameraMode = Enum.CameraMode.LockFirstPerson

local function makerayvisible(ray)
	local midpoint = ray.Origin + ray.Direction/2
	local part = Instance.new("Part")
	part.Parent = game.Workspace
	part.Anchored = true
	part.CFrame = CFrame.new(midpoint, ray.Origin)
	part.Size = Vector3.new(radius,radius,ray.Direction.magnitude)
	part.Material = Enum.Material.Neon
	part.Color = Color3.fromRGB(255, 0, 0)
	part.CanCollide = false
	part.CanQuery = false
	part.Name = "Laser"
	local Info = TweenInfo.new(1)
	local properties = {Transparency = 1}
	local Tween = game:GetService("TweenService"):Create(part,Info,properties)
	Tween:Play()
end

laser.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		local endpoint = Instance.new("Part")
		endpoint.Parent = workspace
		endpoint.Transparency = 1
		endpoint.CanCollide = false
		endpoint.Anchored = true
		endpoint.CanQuery = false
		while uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) == true do
			local thing1 = math.random(0,5)
			local thing2 = math.random(0,5)
			local thing3 = math.random(0,5)			
			
			local point = player:GetMouse().Hit.Position
			endpoint.CFrame = CFrame.new(point + Vector3.new(thing1,thing2,thing3))
			
			local startp = script.Parent.start.Position
			local endp = endpoint.Position - startp
			
			local ray = Ray.new(startp,endp)
			
			makerayvisible(ray)
			local hit, position, normal = game.Workspace:FindPartOnRay(ray)
			if hit then
				local testpart2 = testpart:Clone() 
				testpart2.Parent = workspace.Dots
				testpart2.CFrame = CFrame.new(position, position + normal)
			else
				print("No hit")
			end
			rs.Heartbeat:Wait()
		end
		local descendants = game.Workspace:GetDescendants()
		for _, descendant in pairs(descendants) do
			if descendant.Name == "Laser" then
				descendant:Destroy()
			end
		end
		endpoint:Destroy()
	end)
end)

Any help would be appreciated!

Firstly, you might want to switch to the new workspace:Raycast function as the Ray object is no longer supported and I dont know the issue.

Secondly, you should probably check whether your ray has hit your character.

I converted it over to workspace:Raycast and the same thing still seems to be happening. Though now the visualization function doesn’t work so I just took it out for now. It’s also not hitting my character as it prints “No hit” in the output multiple times, and if it was then there would be floating dots where my character was.

laser.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		local endpoint = Instance.new("Part")
		endpoint.Parent = workspace
		endpoint.Transparency = 1
		endpoint.CanCollide = false
		endpoint.Anchored = true
		endpoint.CanQuery = false
		while uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) == true do
			local thing1 = math.random(0,5)
			local thing2 = math.random(0,5)
			local thing3 = math.random(0,5)			
			
			local point = player:GetMouse().Hit.Position
			endpoint.CFrame = CFrame.new(point + Vector3.new(thing1,thing2,thing3))
			
			local startpart = script.Parent.start		
			local ray = workspace:Raycast(startpart.Position, endpoint.Position - startpart.Position)
			
			if ray then
				local hit = ray.Instance:GetFullName()
				local position = ray.Position
				local normal = ray.Normal
				local testpart2 = testpart:Clone() 
				testpart2.Parent = workspace.Dots
				testpart2.CFrame = CFrame.new(position, position + normal)
			else
				print("No hit")
			end
			rs.Heartbeat:Wait()
		end
		local descendants = game.Workspace:GetDescendants()
		endpoint:Destroy()
	end)
end)