Help with bobbing/floating parts being put at random Y position

I’m making some items that the player can pick up float/bob up and down while spinning (you’ve probably seen what I’m talking about in 100 different games before). What I’ve just noticed is that the lowest point of these items bobbing is for whatever reason being randomized. So if I run multiple play tests the starting Y position of these items bobbing will not be the same. I obviously don’t like this and want it to be consistent across all clients.

Now what’s even more strange is the fact that when running multiple client test I get a bigger difference in starting Y even though THIS IS A LOCAL SCRIPT!!! These objects aren’t even moving on the server at all. It’s not consistent behavior across the clients either some will start the objects way too high or way too low, BUT I find it REAL strange that more clients seems to mean bigger randomization???

Anyways this is a local script set inside of StarterPlayerScripts:

local bob_speed = 3
local bob_dist = 1
local spin_speed = 3

local floatingPickups = game.Workspace.FloatingPickups
local items = floatingPickups:GetChildren()

game:GetService("RunService").Heartbeat:Connect(function(dt)
	for i = 1, #items do
		local model = items[i]
		local part = model.PrimaryPart
		local init_pos = part.Position
		local angleCF = part.CFrame - part.Position
		local newSine = math.sin(tick() * bob_speed)
		model:SetPrimaryPartCFrame(angleCF * CFrame.fromEulerAnglesXYZ(0,spin_speed*dt,0) + init_pos + Vector3.new(0,(newSine*bob_dist)*dt,0))
	end
end)

I’m not a big math guy, but maybe math.sin doesn’t start at the same position of the sine wave each time? That still wouldn’t explain why more client = more random though… anyway I’m clueless on how to fix this.

2 Likes

Your use of sine is correct in this case, but I believe the issue is at the line that sets the CFrame.

I would suggest taking a closer look at the spin_speed integration, because I see that you are changing the Y-axis by doing so.

I simplified your usage just to make sure, as shown in the example below.

https://gyazo.com/73ee783c4829ac43cccba0acd5982cbf

local Speed = 3
local YOffset = 3
local Part = script.Parent
game:GetService("RunService").Heartbeat:Connect(function()
	local Curve = math.sin(tick()*Speed)
	local PartPos = Part.Position
	Part.Position=Vector3.new(PartPos.X,Curve+YOffset,PartPos.Z)
end)
3 Likes