Help with preventing beam glitching

So I have a beam and attachments that are parented to the Humanoid Root Part but when I tried testing it in first person, it works but when you start jumping and moving, the beam starts glitching.

Code:

local attach0 = Instance.new("Attachment")
local attach1 = Instance.new("Attachment")

AimBeam.Attachment0 = attach0
AimBeam.Attachment1 = attach1

attach0.Parent = HumanoidRootPart
attach1.Parent = HumanoidRootPart

local function beamProjectile(gravity, initialVelocity, initialPosition, duration)
	local c = 0.5 * 0.5 * 0.5
	local p3 = 0.5 * gravity * duration * duration + initialVelocity * duration + initialPosition
	local p2 = p3 - (gravity * duration * duration + initialVelocity * duration) / 3
	local p1 = (c * gravity * duration * duration + 0.5 * initialVelocity * duration + initialPosition - c * (initialPosition + p3)) / (3 * c) - p2

	local curve0 = (p1 - initialPosition).Magnitude
	local curve1 = (p2 - p3).Magnitude

	local b = Vector3.new(0, 1, 0) -- Set the beam direction to always point upward
	local r1 = (p1 - initialPosition).Unit
	local u1 = b:Cross(r1).Unit
	local r2 = (p2 - p3).Unit
	local u2 = b:Cross(r2).Unit
	b = r1:Cross(u1).Unit

	local cf1 = CFrame.new(initialPosition.X, initialPosition.Y, initialPosition.Z, r1.X, u1.X, b.X, r1.Y, u1.Y, b.Y, r1.Z, u1.Z, b.Z)
	local cf2 = CFrame.new(p3.X, p3.Y, p3.Z, r2.X, u2.X, b.X, r2.Y, u2.Y, b.Y, r2.Z, u2.Z, b.Z)

	return curve0, -curve1, cf1, cf2
end

local function createAndSetBeam(gravity, initialVelocity, initialPosition, endTime)
	local t1 = endTime or 1
	local curve0, curve1, cf1, cf2 = beamProjectile(gravity, initialVelocity, initialPosition, t1)

	AimBeam.CurveSize0 = curve0
	AimBeam.CurveSize1 = curve1
	AimBeam.Segments = 100 * math.round(t1 * 3)

	attach0.CFrame = HumanoidRootPart.CFrame:Inverse() * cf1 + Vector3.new(2.6, 1.5, -1.5)
	attach1.CFrame = HumanoidRootPart.CFrame:Inverse() * cf2
end

local function aimTrajectory()
	buttonDownConnection = RunService.RenderStepped:Connect(function(delta)
		local endTime = 5

		local direction = (mouse.Hit.Position - HumanoidRootPart.Position).Unit
		local appliedVelocity = direction * projectileSpeed

		createAndSetBeam(gravity, appliedVelocity, HumanoidRootPart.Position, endTime)
	end)
end

1 Like

Could you send the full code so I can test it?

1 Like

Sure.

local RunService = game:GetService("RunService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")

local mouse = player:GetMouse()
mouse.TargetFilter = workspace

local tool = script.Parent
local Handle = tool:WaitForChild("Handle")
local AimBeam = Handle:WaitForChild("AimBeam")

local cooldown = 0.1
local currentTime = cooldown

local canThrow = true

local DataModule = require(script:WaitForChild("DataModule"))

local projectileSpeed = DataModule.ProjectileSpeed
local gravity = DataModule.EffectGravity

local buttonDownConnection

local attach0 = Instance.new("Attachment")
local attach1 = Instance.new("Attachment")

AimBeam.Attachment0 = attach0
AimBeam.Attachment1 = attach1

attach0.Parent = HumanoidRootPart
attach1.Parent = HumanoidRootPart

local function setButtonDownConnectionNil()
	if buttonDownConnection then
		buttonDownConnection:Disconnect()
		buttonDownConnection = nil
	end
end

local function resetAll()
	setButtonDownConnectionNil()
	AimBeam.Enabled = false
	attach0:Destroy()
	attach1:Destroy()
end

local function beamProjectile(gravity, initialVelocity, initialPosition, duration)
	local c = 0.5 * 0.5 * 0.5
	local p3 = 0.5 * gravity * duration * duration + initialVelocity * duration + initialPosition
	local p2 = p3 - (gravity * duration * duration + initialVelocity * duration) / 3
	local p1 = (c * gravity * duration * duration + 0.5 * initialVelocity * duration + initialPosition - c * (initialPosition + p3)) / (3 * c) - p2

	local curve0 = (p1 - initialPosition).Magnitude
	local curve1 = (p2 - p3).Magnitude

	local b = Vector3.new(0, 1, 0) -- Set the beam direction to always point upward
	local r1 = (p1 - initialPosition).Unit
	local u1 = b:Cross(r1).Unit
	local r2 = (p2 - p3).Unit
	local u2 = b:Cross(r2).Unit
	b = r1:Cross(u1).Unit

	local cf1 = CFrame.new(initialPosition.X, initialPosition.Y, initialPosition.Z, r1.X, u1.X, b.X, r1.Y, u1.Y, b.Y, r1.Z, u1.Z, b.Z)
	local cf2 = CFrame.new(p3.X, p3.Y, p3.Z, r2.X, u2.X, b.X, r2.Y, u2.Y, b.Y, r2.Z, u2.Z, b.Z)

	return curve0, -curve1, cf1, cf2
end

local function createAndSetBeam(gravity, initialVelocity, initialPosition, endTime)
	local t1 = endTime or 1
	local curve0, curve1, cf1, cf2 = beamProjectile(gravity, initialVelocity, initialPosition, t1)

	AimBeam.CurveSize0 = curve0
	AimBeam.CurveSize1 = curve1
	AimBeam.Segments = 100 * math.round(t1 * 3)

	attach0.CFrame = HumanoidRootPart.CFrame:Inverse() * cf1 + Vector3.new(2.6, 1.5, -1.5)
	attach1.CFrame = HumanoidRootPart.CFrame:Inverse() * cf2
end

local function aimTrajectory()
	buttonDownConnection = RunService.RenderStepped:Connect(function(delta)
		local endTime = 5

		local direction = (mouse.Hit.Position - HumanoidRootPart.Position).Unit
		local appliedVelocity = direction * projectileSpeed

		createAndSetBeam(gravity, appliedVelocity, HumanoidRootPart.Position, endTime)
	end)
end

mouse.Button1Down:Connect(function()
	if canThrow and tool:IsDescendantOf(character) and tick() - currentTime >= cooldown then
		AimBeam.Enabled = true
		aimTrajectory()
	end
end)

mouse.Button1Up:Connect(function()
	if canThrow and tool:IsDescendantOf(character) and tick() - currentTime >= cooldown then
		currentTime = tick()
		local mouseHit = mouse.Hit.Position
		local startPos = attach0.WorldPosition
		
		script.ServerSender:FireServer(startPos, mouseHit)
		setButtonDownConnectionNil()
		AimBeam.Enabled = false
	else
		resetAll()
	end
end)

tool.Destroying:Connect(function()
	resetAll()
end)

humanoid.Died:Connect(function()
	canThrow = false
	resetAll()
end)

I think its something wrong with the player mouse, I tried attaching 2 attachments in the Root and set the beam and it works fine.

1 Like

So does this solve your problem or you still need help?

1 Like

I still need help. Is there a problem in first person that the mouse position is off when moving?

I tried:

RunService.Stepped:Connect(function(delta)

it works better but it still glitches a little.

1 Like

I don’t think the problem is from the mouse, I tried using the middle point of the screen and convert it to 3D space point but same results:

local function aimTrajectory()
	buttonDownConnection = RunService.Stepped:Connect(function(delta)
		local endTime = 5

		local Vector = Vector2.new(workspace.CurrentCamera.ViewportSize.X / 2, workspace.CurrentCamera.ViewportSize.Y / 2  - (game:GetService("GuiService"):GetGuiInset().Y/2))
		local mouseUnitRay = workspace.CurrentCamera:ScreenPointToRay(Vector.X, Vector.Y)
		local direction = mouseUnitRay.Direction 
		local appliedVelocity = direction * projectileSpeed

		createAndSetBeam(gravity, appliedVelocity, HumanoidRootPart.Position, endTime)
	end)
end

So whats the problem? Attaching a beam to the character manually works fine but when using a mouse, it gets glitchy.

The problem is not from your code it’s from the Roblox render system and I think you are right, in first person mode the mouse hit position does not change that fast while jumping because you are not moving the mouse you moving the character that’s why it’s late a little, it’s faster using RunService.Stepped but still not enough that’s why it glitchs sometimes, the same thing for this:

take a look at this simple script, it also keeps glitching in it:

local RunService = game:GetService("RunService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")

local mouse = player:GetMouse()


local Beam = Instance.new("Beam",HumanoidRootPart)
local att0 = Instance.new("Attachment",HumanoidRootPart)
local att1 = Instance.new("Attachment",HumanoidRootPart)

Beam.Attachment0 = att0
Beam.Attachment1 = att1
Beam.FaceCamera = true

function Update()
	att0.WorldPosition = HumanoidRootPart.CFrame.Position
	att1.WorldPosition = mouse.Hit.p
end

RunService.RenderStepped:Connect(Update)

so the problem is from the engine and sadly you can’t do anything about it, your best option now is to just use RunService.Stepped it’s the fastest looping event available in Roblox.

How does Bedwars do it? Theirs never glitch.

Also, using Stepped makes it glitch when you move around in third person but Heartbeat doesn’t.

1 Like

Now I got it, I was wrong the mouse is not the problem it’s because in first person mode the HumanoidRootPart move with the camera so the two attachment inside of it move too in the same time your script keep updating the attachment position, I was able to solve it in this exemple by adding the second attachment into other part not the HumanoidRootPart

but when I did that in your code it glitch another way, you can test it by yourself if you want:

local RunService = game:GetService("RunService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")

local mouse = player:GetMouse()
mouse.TargetFilter = workspace

local tool = script.Parent
local Handle = tool:WaitForChild("Handle")
local AimBeam = Handle:WaitForChild("AimBeam")

local cooldown = 0.1
local currentTime = cooldown

local canThrow = true



local DataModule = require(script:WaitForChild("DataModule"))

local projectileSpeed = DataModule.ProjectileSpeed
local gravity = DataModule.EffectGravity

local buttonDownConnection

local FakePart = Instance.new("Part",game.Workspace)
FakePart.Massless = true
FakePart.Anchored = true
FakePart.Size = Vector3.new(0.1,0.1,0.1)
FakePart.Transparency = 1

local attach0 = Instance.new("Attachment",HumanoidRootPart)
local attach1 = Instance.new("Attachment",FakePart)

AimBeam.Attachment0 = attach0
AimBeam.Attachment1 = attach1


local function setButtonDownConnectionNil()
	if buttonDownConnection then
		buttonDownConnection:Disconnect()
		buttonDownConnection = nil
	end
end

local function resetAll()
	setButtonDownConnectionNil()
	AimBeam.Enabled = false
	attach0:Destroy()
	attach1:Destroy()
end

local function beamProjectile(gravity, initialVelocity, initialPosition, duration)
	local c = 0.5 * 0.5 * 0.5
	local p3 = 0.5 * gravity * duration * duration + initialVelocity * duration + initialPosition
	local p2 = p3 - (gravity * duration * duration + initialVelocity * duration) / 3
	local p1 = (c * gravity * duration * duration + 0.5 * initialVelocity * duration + initialPosition - c * (initialPosition + p3)) / (3 * c) - p2

	local curve0 = (p1 - initialPosition).Magnitude
	local curve1 = (p2 - p3).Magnitude

	local b = Vector3.new(0, 1, 0) -- Set the beam direction to always point upward
	local r1 = (p1 - initialPosition).Unit
	local u1 = b:Cross(r1).Unit
	local r2 = (p2 - p3).Unit
	local u2 = b:Cross(r2).Unit
	b = r1:Cross(u1).Unit

	local cf1 = CFrame.new(initialPosition.X, initialPosition.Y, initialPosition.Z, r1.X, u1.X, b.X, r1.Y, u1.Y, b.Y, r1.Z, u1.Z, b.Z)
	local cf2 = CFrame.new(p3.X, p3.Y, p3.Z, r2.X, u2.X, b.X, r2.Y, u2.Y, b.Y, r2.Z, u2.Z, b.Z)

	return curve0, -curve1, cf1, cf2
end

local function createAndSetBeam(gravity, initialVelocity, initialPosition, endTime)
	local t1 = endTime or 1
	local curve0, curve1, cf1, cf2 = beamProjectile(gravity, initialVelocity, initialPosition, t1)

	AimBeam.CurveSize0 = curve0
	AimBeam.CurveSize1 = curve1
	AimBeam.Segments = 100 * math.round(t1 * 3)

	attach0.CFrame = HumanoidRootPart.CFrame:Inverse() * cf1 + Vector3.new(2.6, 1.5, -1.5)
	attach1.CFrame = FakePart.CFrame:Inverse() * cf2
end

local function aimTrajectory()
	buttonDownConnection = RunService.RenderStepped:Connect(function(delta)
		local endTime = 5

		local direction = (mouse.Hit.Position - HumanoidRootPart.Position).Unit
		local appliedVelocity = direction * projectileSpeed

		createAndSetBeam(gravity, appliedVelocity, HumanoidRootPart.Position, endTime)
	end)
end

mouse.Button1Down:Connect(function()
	if canThrow and tool:IsDescendantOf(character) and tick() - currentTime >= cooldown then
		AimBeam.Enabled = true
		aimTrajectory()
	end
end)

mouse.Button1Up:Connect(function()
	if canThrow and tool:IsDescendantOf(character) and tick() - currentTime >= cooldown then
		currentTime = tick()
		local mouseHit = mouse.Hit.Position
		local startPos = attach0.WorldPosition

		script.ServerSender:FireServer(startPos, mouseHit)
		setButtonDownConnectionNil()
		AimBeam.Enabled = false
	else
		resetAll()
	end
end)

tool.Destroying:Connect(function()
	resetAll()
end)

humanoid.Died:Connect(function()
	canThrow = false
	resetAll()
end)

it’s because the script still updating the first attachment while it’s turning with the HumanoidRootPart and I don’t know how to solve it, taking the first attachment out of the HRP will make it glitch even more.

2 Likes

So theres no way to solve this? I also tried using every loop but none of them worked.