# How to animate objects with bobbing up and down motion in Unity?

I have created a 2D platform game with Unity and C# where I have collectable items that can be picked up by the player. What I want is to give the items more focus by having them bobbing up and down.

I came up with the following version:

Vector2 floatY;

public float FloatStrength; // Set strength in Unity

void Update () {
floatY = transform.position;
floatY.y = (Mathf.Sin(Time.time) * FloatStrength);
transform.position = floatY;
}


But, this makes the object float in the middle of the level instead of where the object is positioned. How can I fix that?

Here is a screenshot of the prototype of the game:

The player can collect the wood stumps which should be bobbing up and down in space just above the ground.

• Why don't you tell us what you've tried? That'll give people a starting point and makes it more likely for you to get an answer that you can use. It's likely you're looking for simple harmonic motion.
– House
Mar 18 '15 at 19:26
• use a sine wave to determine the amount to move and the direction per frame and adjust the y pos on your floating object ... assuming y is up and down. This question is so vague that's about the best I can suggest without clarity.
– War
Mar 18 '15 at 19:34
• @Wardy, I have update my code and I think this is what you suggest. Is that right? Mar 18 '15 at 19:36
• @AlexandreVaillancourt Do you mean if it is 2D or 3D? It's a 2D plaformer. Mar 18 '15 at 19:42
• I have update the question. Mar 18 '15 at 20:05

You have a pretty simple solution. What your problem here is that you are not preserving the original y position. Essentially, you need to store the original y position in a variable, that would look like this: (Don't forget to set the variable in the Start() function.)

Vector2 floatY;
float originalY;

public float floatStrength;

void Start ()
{
this.originalY = this.transform.position.y;
}

void Update () {
floatY = transform.position;
floatY.y = (Mathf.Sin(Time.time) * floatStrength);
transform.position = floatY;
}


After that, I suggest that instead of directly setting the y value of the floatY to Mathf.Sin(Time.time) * floatStrength, you set it based on the sum of that value and the original transform position. The final code should look something like this:

Vector2 floatY;
float originalY;

public float floatStrength;

void Start ()
{
this.originalY = this.transform.position.y;
}

void Update () {
floatY = transform.position;
floatY.y = originalY + (Mathf.Sin(Time.time) * floatStrength);
transform.position = floatY;
}


Finally, instead of storing floatY as a Vector, you could store it as a float. Alternatively, you could use transform.position directly, doing something like this:

Vector2 floatY;
float originalY;

public float floatStrength;

void Start ()
{
this.originalY = this.transform.position;
}

void Update () {
/* Old code:
floatY = transform.position;
floatY.y = originalY + (Mathf.Sin(Time.time) * floatStrength);
transform.position = floatY;
*/
transform.position = new Vector2(transform.position.x,
originalY + (Math.Sinf(Time.time) * floatStrength));
}


Finally, the last step is to do some minor refactoring as to remove some errors that have popped up along the way. Math.Sin (Note: not Math.Sinf) yields a double instead of the desired float, so we have to explicitly convert that value. Next, we can remove the Vector2 floatY completely. Note that this would need to actually be a Vector3 to store transform.position, as that also has a z component, if we were to actually have kept using that. Finally, we must fix that same problem in the Update() function, and change:

    transform.position = new Vector2(transform.position.x,
originalY + (Math.Sinf(Time.time) * floatStrength));


to:

    transform.position = new Vector3(transform.position.x,
originalY + (Math.Sinf(Time.time) * floatStrength), transform.position.z);


That code segment does not implement the other changes that I mentioned. In the end the complete code is as follows:

using UnityEngine;
using System;
using System.Collections;

public class FloatBehavior : MonoBehaviour
{
float originalY;

public float floatStrength = 1; // You can change this in the Unity Editor to
// change the range of y positions that are possible.

void Start()
{
this.originalY = this.transform.position.y;
}

void Update()
{
transform.position = new Vector3(transform.position.x,
originalY + ((float)Math.Sin(Time.time) * floatStrength),
transform.position.z);
}
}


Note that this code can be attached to an object either through New Object >> 2D >> Sprite and then by adding this code as a script, or through the following code programmatically:

    GameObject object = new GameObject();
object.name = "Floating Box";


Here's an example of what this could look like:

Edit: Fixed compile errors

• Thanks Pip for the answer. Unfortunately, I receive the following error: The referenced script on this Behaviour is missing!. The floated object have a box collider 2D and a Rigidbody2D. Mar 18 '15 at 21:26
• @Caspert can you include a screenshot of the error, a pastebin of the code, and the line number that that occurred on?
– Pip
Mar 18 '15 at 23:48
• @Caspert also, I suggest removing the Rigidbody2D while keeping the box collider, as you don't actually need it in this case. If you do not have a SpriteRenderer on the object, I suggest adding one and using the image with that rather than rendering it directly.
– Pip
Mar 19 '15 at 12:18
• here is the error that I receive after past your code in mine. i59.tinypic.com/2aeo41g.jpg Mar 19 '15 at 19:03
• @Caspert the issue here is a missing semicolon, which I have fixed. Next time, try playing around with the code before you ask a question, and then you can edit the answer as needed.
– Pip
Mar 19 '15 at 19:09

I use this for my 3D game:

using UnityEngine;
using System;
using System.Collections;

public class BobbingEffect : MonoBehaviour
{
float originalY;

public float floatStrength = 1; // You can change this in the Unity Editor to
// change the range of y positions that are possible.

void Start()
{
this.originalY = this.transform.position.y;
}

void Update()
{
transform.position = new Vector3(transform.position.x,
originalY + ((float)Math.Sin(Time.time) * floatStrength),
transform.position.z);
transform.Rotate(0,1,0);
}
}

• How is this solution different from the one posted 3 years ago? In fact it looks like a copy&paste from the last code snippet from the old answer, just with a transform.Rotate(0,1,0); added to it. Can you tell us what that line does and why it's an improvement? Feb 8 '21 at 15:06