Making floating parts that goes up and down

You should use the math.rad() as the mat.sin() takes radian value, and the i is a degree value so it should be like this: math.sin(math.rad(i)) * 0.4

1 Like

How would I do it with tick()?

Ok so what code are you using right now cuz i am confused?
Edit: the tick() method can be only used if you have a StartPosition variable because otherwise it can have instability issues

Ok, so this is my code right now.

while true do
	for i = 1, 360, 1 do
		script.Parent.Position += Vector3.new(0, math.sin(i) * 0.4, 0)
		task.wait(0.15)
	end
end

If I were to use tick(), my starting position is my current position. Do I need the speed variable in my code? like to adjust the speed, instead of adjusting the wait time since it will be janky.

1 Like

when you use for loop then you shouldn’t use tick() as here is the reason:
When you have a StartPosition variable that never changes then you can use tick() as it will make it slightly more accurate.
But when you add the the current Position, you shouldn’t use tick() as for every loop the values will not me the same (they will be slightly off). And after like the object completed for example 50 loops, the object might not be at the same position, it might be slightly higher or lower than it should be. Your current implementation is good. You could make a Attribute for your objects that would be the StartPosition but it would be harder to manage all obejcts.

Edit: you can make the speed higher doing something like this:

while true do
	for i = 0, 360, Speed do --you need a new speed variable
		script.Parent.Position += Vector3.new(0, math.sin(math.rad(i)) * 0.4, 0)
		task.wait(0) --we put it to zero so the code happens every frame
	end
end

But remember that when you divide 360 / Speed, it cannot have decimal numbers or it will have instability issues. So you cannot set speed to 7 as you cannot divide 360 / 7 without having decimal numbers.

2 Likes

I don’t know if the code works but it probably should.

1 Like

How is it more accurate?

And for this, will it work if I just remove the for loop?
tick() returns a different value as time passes, though I still don’t know how math.sin(tick()) would work.

And I think this will crash the game man.

So. The let’s say the code runs 60 fps. It means it will run every 0.01666666666 seconds. But it is never perfect so a frame could actually take slight higher or slightly lower time like for example: 0.016334464 or 0.17000034. In the for loop, it assumes that it will always be perfect timing but it is not true. So we can use tick() to get the time that represents the timing more accuratelly but it will need a StartPosition variable, and beause you move the object every frame by subtracting or adding to the current position, we don’t have an actual position where the object should be. So after some time, the object will be higher or lower than it should be (it will broke even faster when the fps is not stable).

It will not crash the game. You actually cannot wait 0 seconds as it is not possible, instead, when we put it to 0 the code will resume on the next resumption point which will be the next frame. And by frame i am talking about scripts Fps, not the Fps of the rendering, which is why i told you about the RenderStepped method before as if users use third-party application to unlock their fps to higher than 60 then the objects position will update every script frame rate instead of render frame rate which makes it look not smooth. The RenderStepped method will actually use the render frame rate but you cannot use it because you don’t have a StartPosition variable, and making it will require you to have a better structure for storing your objects data.

2 Likes

Ok, so I believe I will be needing a startPosition variable in every case, just to prevent issues.

Do while loops run at 60 fps? and how do scripts fps work. I only know the rendering of the frames.

The part moved very smoothly, but for some reason, I think the math.sin() never returned a negative value. The part moved so high up, like I want it to only move up and down slightly. In terms of performance, the script will have a high activity.

Lastly, will this fix the issue I have in the first place? like to move a lot of parts up and down at the same time?

Sorry for being late, busy with school.

1 Like

I optimized and created you a script using one line for the animation using Lerp Animating.

Also made the apple spin on one axis for you.

local CS = game:GetService("CollectionService")

local function whileTask(Variable)
	local Sine = 0
	local OGCF = Variable.CFrame
	while true do
		task.wait()
		Sine += 1 --Infinite Sinewave Num
		Variable.CFrame = OGCF:Lerp(CFrame.new(0,math.sin(Sine/10)*2,0),0.25) --Lerp animation
		Variable.Orientation = Vector3.new(0,Sine,0)
	end
end

for Index,Variable in pairs(CS:GetTagged("Apple")) do
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end

CS:GetInstanceAddedSignal("Apple"):Connect(function(Variable)
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end)

The lerp animation bit is sort of complicated, and I don’t wish to explain it here. You can read about Lerp and Trigonometry online.

P.S. It may be more efficient to iterate through everything in the while loop or it may be more efficient the way I programmed it. I am unsure. You can also change the “true” in while true do to task.wait() and remove the task.wait() in the loop and it’ll function the same. Cheers!

1 Like

I forgot to mention, please run this on the client and possibly switch the while loop to a renderstepped connection instead. Running it on the server can get some weird results if you tab out.

You can also change the multiply by 2 after the sin equation to make the up and down motion more dramatic.

1 Like

The apples were moving up and down sooooo fast for some reason.

1 Like

It should look like this.

And this should be the exact localscript

local CS = game:GetService("CollectionService")

local function whileTask(Variable)
	local Sine = 0
	local OGCF = Variable.CFrame
	while true do
		task.wait()
		Sine += 1 --Infinite Sinewave Num
		Variable.CFrame = OGCF:Lerp(CFrame.new(0,math.sin(Sine/10)*2,0) * CFrame.Angles(0,math.rad(Sine*10),0),0.25) --Lerp animation
	end
end

for Index,Variable in pairs(CS:GetTagged("Apple")) do
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end

CS:GetInstanceAddedSignal("Apple"):Connect(function(Variable)
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end)
1 Like

Ahh wait that’s my bad.

Use this.

local CS = game:GetService("CollectionService")

local function whileTask(Variable)
	local Sine = 0
	local OGCF = Variable.CFrame
	while true do
		task.wait()
		Sine += 1 --Infinite Sinewave Num
		Variable.CFrame = OGCF:Lerp(CFrame.new(0,math.sin(Sine/10)*2,0) * CFrame.Angles(0,math.rad(Sine*10),0),0.25) --Lerp animation
	end
end

for Index,Variable in pairs(CS:GetTagged("Apple")) do
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end

CS:GetInstanceAddedSignal("Apple"):Connect(function(Variable)
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end)
1 Like

If this works as intended please mark what I am replying to as the answer so people can see the more in depth explanation. I have updated the reply to use the new script.

1 Like

Uhhh

robloxapp-20240131-2114421.wmv (356.9 KB)

1 Like

I am investigating this issue, and it’s pretty odd. I don’t really know why that happens because it works fine with 1,1,1 scale parts. Give me a moment.

1 Like

I believe this is an issue with Roblox.
I used math.abs to obtain the absolute and still got the same result.

CFrame.Angles() seems to be affected by this, while orientation does not.

local CS = game:GetService("CollectionService")

local function whileTask(Variable)
	local Sine = 0
	local OGCF = Variable.CFrame
	while true do
		task.wait()
		Sine += 1 --Infinite Sinewave Num
		Variable.CFrame = OGCF:Lerp(CFrame.new(0,math.sin(Sine/10)*2,0),0.25) --Lerp animation
		Variable.Orientation = Vector3.new(0,Sine,0)
	end
end

for Index,Variable in pairs(CS:GetTagged("Apple")) do
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end

CS:GetInstanceAddedSignal("Apple"):Connect(function(Variable)
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end)

Try this ^ and again, mark the post I said to mark as the answer if it works.

You can make the spin faster by multiplying sine by a number eg Sine*2

2 Likes

It works but the script activity is so high, also if I want to move the part to another position while still moving up and down, it won’t move. It’s basically a snake game. I don’t destroy the food, instead I just move it to a random position. The food moving up and down is essentially just for the visuals. I think it is best to get it done on the client.

I have a part welded to the apple and it is spinning crazily, when the apple is spinning slowly.

local CS = game:GetService("CollectionService")

local function whileTask(Variable)
	local Sine = 0
	local OGCF = Variable.PrimaryPart.CFrame
	while true do
		task.wait()
		Sine += 1 --Infinite Sinewave Num
		Variable.PrimaryPart.CFrame = OGCF:Lerp(CFrame.new(0,math.sin(Sine/10)*2,0),0.25) --Lerp animation
		Variable.PrimaryPart.Orientation = Vector3.new(0, Sine, 0)
	end
end

for Index,Variable in pairs(CS:GetTagged("Apple")) do
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end

CS:GetInstanceAddedSignal("Apple"):Connect(function(Variable)
	task.spawn(whileTask,Variable) --Spawn task with WhileTask, pass variable Variable
end)
1 Like

Could you send a video of what happens or a file?