You’re only tweening the size of it, it shrinks/grows from the origin position of the part, so it behaves how you’ve told it to. You would want to have the beam begin very small along the axis it expands on, positioned at the hilt of the saber. Tween the Position to move from the hilt to half the distance to the end of the blade, and tween the Size only on the one axis from ~0 to its full length. It’ll make it grow as fast as it is moving so it will look like a continuous beam growing from the hilt.
Right, because your logic behind moving the parts from [...].Position + Vector3.new(-1, 0, 0) to [...].Position + Vector3.new(1, 0, 0) isn’t a proper reference to and from the hilt of the saber, you’re just adding a world vector to its old position. I wrote a quick example in studio to explain what I mean about the position:
local TweenService = game:GetService("TweenService")
local hilt = script.Parent.hilt
local blade = script.Parent.blade
local goal = {}
goal.Position = blade.Position
goal.Size = blade.Size
--Before the animation plays, I grab its current positions.
blade.CFrame = hilt.CFrame
blade.Size = blade.Size * Vector3.new(1,0,1)
--Now I flatten the blade and place it inside of the hilt.
TweenService:Create(blade, TweenInfo.new(2, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, -1, true), goal):Play()
--Now I tween the blade from the hilt(off) position to its original(on) position.
--For demo purposes it's set to infinitely loop back and forth.
This is just two parts that I roughly threw together to look like a sword in a model with a LocalScript. The blade is tall and above the hilt on the y-axis