Make Tween both Bob up and Down and Spin using a CFrame

I’m trying to get a Tween that’s suppose to be spinning to create a bobbing up and down motion at the same time. So, the tween should be both bobbing up and down and spinning in a circle until the tween is told to stop.

Problem is, this formula doesn’t spin constantly. It turns, then turns back the same direction it came from, looking more like a swiveling sentry than a spinning device. Increase the number doesn’t work.

local tweenInfo = TweenInfo.new(BOUNCE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, math.huge, true, 0)

local tween = TweenService:Create(_part, tweenInfo, { CFrame = _part.CFrame * CFrame.Angles(0, math.rad(180), 0) + Vector3.new(0, BOUNCE_HEIGHT, 0)  } )
		
while clock.PrimaryPart.Transparency == 0 do
	wait()
end

tween:Cancel()

The issue you are facing is because the formula you are using for the rotation is causing the part to rotate back and forth instead of continuously spinning. To create a smooth spinning motion, you should incrementally update the rotation angle over time.

Here’s how you can modify your code to achieve the desired bobbing up and down motion along with continuous spinning:

local BOUNCE_HEIGHT = 5
local SPIN_SPEED = math.rad(180)  -- Adjust the speed as desired
local BOUNCE_TIME = 1

local function SpinBobbingPart(part)
    local startTime = tick()
    local function Update()
        local elapsedTime = tick() - startTime
        local bounceOffset = BOUNCE_HEIGHT * math.sin(math.pi * elapsedTime / BOUNCE_TIME)
        local spinAngle = SPIN_SPEED * elapsedTime

        local newCFrame = CFrame.new(part.Position) * CFrame.Angles(0, spinAngle, 0) + Vector3.new(0, bounceOffset, 0)
        part.CFrame = newCFrame

        if elapsedTime >= BOUNCE_TIME then
            return
        end

        task.wait()
        Update()
    end

    Update()
end

local part = _part  -- Replace with your part reference
SpinBobbingPart(part)
1 Like

Heads up, a recursive function is always significantly slower than a loop. That’s generally applicable to every programming language.

I do appreciate the use of sin when addressing this. I had a similar formula before seeing if TweenService would be better performance wise due to there being up to 100 of these objects moving and then being returned to a pool.

Since the TweenInfo has reverse set to true, I can see why the problem would occur. It might be better if I created a loop with the two tweens and a check for the Transparency condition to break the tweens as that’s a vital part.
Unfortunately, with that I am suspecting it wouldn’t break out of the loop until the tweens have completed, which could be an issue.