You could probably use a local script that on every frame (Or a server script on Stepped event), sets the balloon’s Y position to some value + the sine of os.clock() multiplied by a speed and then multiplying that result for the variance in height. Here’s how the movement would look:
since it doesn’t seem to be important to the gameplay, I guess you could just define a table of positions that the baloon can follow and tween it all on the client
Loop through the table → get the position → tween to that position → the tween’s .Completed signal fires → go to next position etc…
local speed = 0.05
local heightDiff = 5
local blimp: Part = workspace.Blimp
-- you can change this ^ to the blimp's root part (where everything is connected to)
game["Run Service"].RenderStepped:Connect(function()
blimp.Position = Vector3.new(
blimp.Position.X,
100 + heightDiff*math.sin(os.clock()*speed),
blimp.Position.Z
)
end)
local speed = 0.3
local heightDiff = 3
local movespeed = 0.05
-- speed at which the blimp moves around the map
local radius = 200
--distance from center of map
local blimp: Part = workspace.Blimp
-- you can change this ^ to the blimp's root part (where everything is connected to)
game["Run Service"].RenderStepped:Connect(function()
blimp:PivotTo(CFrame.new(
math.sin(os.clock()*movespeed)*radius,
100 + heightDiff*math.sin(os.clock()*speed),
math.cos(os.clock()*movespeed)*radius
) * CFrame.Angles(0,math.pi/2 + (os.clock()*movespeed),0)
)
end)
@RobotThom1 had a great solution but make sure to account for the player frame rate so everything is synced up and matching the speed you want it to be at. You can achieve this by including deltaTime.
local speed = 0.3
local heightDiff = 3
local movespeed = 0.05
local radius = 200
local blimp = workspace.Blimp
local timeElapsed = 0
game["Run Service"].RenderStepped:Connect(function(deltaTime)
timeElapsed = timeElapsed + deltaTime
local x = math.sin(timeElapsed * movespeed) * radius
local y = 100 + heightDiff * math.sin(timeElapsed * speed)
local z = math.cos(timeElapsed * movespeed) * radius
local rotation = timeElapsed * movespeed
blimp:PivotTo(CFrame.new(x, y, z) * CFrame.Angles(0, math.pi/2 + rotation, 0))
end)