# 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. Commented Mar 18, 2015 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
Commented Mar 18, 2015 at 19:34
• @Wardy, I have update my code and I think this is what you suggest. Is that right? Commented Mar 18, 2015 at 19:36
• @AlexandreVaillancourt Do you mean if it is 2D or 3D? It's a 2D plaformer. Commented Mar 18, 2015 at 19:42
• I have update the question. Commented Mar 18, 2015 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. Commented Mar 18, 2015 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
Commented Mar 18, 2015 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
Commented Mar 19, 2015 at 12:18
• here is the error that I receive after past your code in mine. i59.tinypic.com/2aeo41g.jpg Commented Mar 19, 2015 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
Commented Mar 19, 2015 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? Commented Feb 8, 2021 at 15:06