My guess is that when you transition from one animation state to another that you do not reset the properties you animate.
When you start playing a new property animation it will stop the old one and start animating from the value the property had when stopped.
So imagine that you animation game object scale y from 1.0 to 2.0 in a repeated ping pong animation. This will keep animating the y scale over and over from 1.0 to 2.0 and back down to 1.0 again, with the easing function you specified.
Let’s now say that you start a new scale y animation with a
to value of 1.5. This will immediately cancel the current animation and start animating from current scale y to 1.5. This means that sometimes it might animate from 1.0 to 1.5 and sometimes from 1.4 to 1.5 and other times from 2.0 to 1.5.
To solve this you should always make a habit of reseting the value:
local function idle(id)
-- cancel the current animation (not strictly necessary since we start a new one below)
-- reset scale (assuming 1.0 is default scale)
go.set(id, "scale.y", 1.0)
-- start the idle animation again going back and forth between 1.0 and 1.5
local duration = 2.0
local to = 1.5
go.animate(id, "scale.y", go.PLAYBACK_LOOP_PINGPONG, to, duration)