TweenService in loop issue

Hello, I am making a system of beams connecting between HumanoidRootPart and “closestPart” but I have a problem with beam attachment1 which is in Tween Position and in the loop. I want Attachemnt 1 to go from HumanoidRootPart to “closestPart” but its position is defined in a loop so something strange is going on with this attachment. Please help and sorry for a low details but I don’t know how to describe it. Maybe a short video will help.

Short video about issue:

local Player = game:GetService("Players").LocalPlayer
local HumanoidRootPart = Player.Character:WaitForChild("HumanoidRootPart")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Hacking = ReplicatedStorage.RemoteEvents:WaitForChild("Hacked")

local TweenService = game:GetService("TweenService")
local TweenInfo = TweenInfo.new(1)

local Beam = Instance.new("Beam")
local Attachment0 = Instance.new("Attachment")
local Attachment1 = Instance.new("Attachment")
local ProximityPrompt = Instance.new("ProximityPrompt")

local Info = Player:WaitForChild("PlayerInformation")
local DistanceValue = Info:WaitForChild("Distance")
local HoldingDuration = Info:WaitForChild("HoldingDuration")

local Cooldown = 5
local Debounce = true

RunService.Heartbeat:Connect(function()
	if script.Equipped.Value == true and Debounce == true then
		local closestMagnitude, closestPart = math.huge, nil
		for _, parts in pairs(game.Workspace.Hackable:GetDescendants()) do
			if parts.Name == "BasePart" then
				local distance = (HumanoidRootPart.Position - parts.Position).Magnitude
				if distance < closestMagnitude then
					closestPart = parts --ISSUE STARTS HERE
					Attachment1.Parent = closestPart
					Attachment1.Position = HumanoidRootPart.Position
					local PlrToBasePart = TweenService:Create(Attachment1, TweenInfo, {WorldPosition = Vector3.new(closestPart.Position.X, closestPart.Position.Y,closestPart.Position.Z)})
					closestMagnitude = distance
					Attachment0.Parent = HumanoidRootPart
					ProximityPrompt.Parent = closestPart
					Beam.Parent = HumanoidRootPart
					Beam.Attachment0 = Attachment0
					Beam.Attachment1 = Attachment1
					PlrToBasePart:Play()
					Beam.LightEmission = 1
					Beam.LightInfluence = 1
					Beam.Segments = 100
					ProximityPrompt.Enabled = true
					ProximityPrompt.HoldDuration = HoldingDuration.Value
					ProximityPrompt.MaxActivationDistance = 70
					ProximityPrompt.RequiresLineOfSight = false
					ProximityPrompt.Style = "Custom"
					ProximityPrompt.Exclusivity = Enum.ProximityPromptExclusivity.AlwaysShow
				end
				if closestMagnitude > DistanceValue.Value then
					Beam.Attachment1 = nil
					ProximityPrompt.Enabled = false
				end
			end
		end
	elseif script.Equipped.Value == false then
		Beam.Attachment1 = nil
		ProximityPrompt.Enabled = false
	end
end)

Are you using TweenService to make the beam smoothly move to the target?
If I’m reading this correctly, it seems like you are creating and playing a tween every single frame.
In the video you’ve given, it looks like the attachment is struggling to tween to where it needs to be.

Yeah, Im using TweenService to make the beam smoothly and You read it correctly. Do you know how to repair it?

You need to make sure your debounce is set up correctly. Otherwise, it’ll work in strange ways.

The problem is that the portion of the code that should be executed only once is being executed many times. I separated this code into two functions.

For it to work correctly it must first calculate which of the parts is closest and perform the action for only one of them (outside the loop).

I added a variable prevClosestPart to know when you are close to one part of the other or not close to any part. This way the functions I mentioned before will only be executed once.

I also changed the tween to work with CFrames. This way it is easier to do the calculations.

local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Hacking = ReplicatedStorage.RemoteEvents:WaitForChild("Hacked")

local TweenService = game:GetService("TweenService")
local TweenInfo = TweenInfo.new(1)

local Beam = Instance.new("Beam")
local Attachment0 = Instance.new("Attachment")
local Attachment1 = Instance.new("Attachment")
local ProximityPrompt = Instance.new("ProximityPrompt")

--local Info = Player:WaitForChild("PlayerInformation")  -- I commented this only for testing purposes
local DistanceValue = 20--Info:WaitForChild("Distance")
local HoldingDuration = 2--Info:WaitForChild("HoldingDuration")

local Cooldown = 5
local Debounce = true

function OnNear(closestPart)
	Attachment1.Parent = closestPart
	Attachment1.CFrame = closestPart.CFrame:ToObjectSpace(HumanoidRootPart.CFrame)
	local PlrToBasePart = TweenService:Create(Attachment1, TweenInfo, {CFrame = CFrame.new()})
	Attachment0.Parent = HumanoidRootPart
	ProximityPrompt.Parent = closestPart
	ProximityPrompt.Enabled = true
	Beam.Parent = HumanoidRootPart
	Beam.Attachment0 = Attachment0
	Beam.Attachment1 = Attachment1
	PlrToBasePart:Play()
	Beam.LightEmission = 1
	Beam.LightInfluence = 1
	Beam.Segments = 100
	ProximityPrompt.Enabled = true
	ProximityPrompt.HoldDuration = HoldingDuration
	ProximityPrompt.MaxActivationDistance = 70
	ProximityPrompt.RequiresLineOfSight = false
	ProximityPrompt.Style = "Custom"
	ProximityPrompt.Exclusivity = Enum.ProximityPromptExclusivity.AlwaysShow
end

function OnFar()
	Beam.Attachment1 = nil
	ProximityPrompt.Enabled = false
end

local prevClosestPart = nil
RunService.Heartbeat:Connect(function()
	if script.Equipped.Value == true and Debounce == true then
		local closestMagnitude, closestPart = math.huge, nil
		for _, parts in pairs(workspace.Hackable:GetDescendants()) do
			if parts.Name == "BasePart" then
				local distance = (HumanoidRootPart.Position - parts.Position).Magnitude
				if distance < closestMagnitude and distance < DistanceValue then
					closestPart = parts
					closestMagnitude = distance
				end
			end
		end
		if closestPart then
			if closestPart ~= prevClosestPart then
				OnNear(closestPart)
				prevClosestPart = closestPart
			end
		else
			OnFar()
			prevClosestPart = nil
		end
	elseif script.Equipped.Value == false then
		Beam.Attachment1 = nil
		ProximityPrompt.Enabled = false
	end
end)
1 Like

Thank you! it works :smiley: