# 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. – MichaelHouse 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? – Caspert Mar 18 '15 at 19:36
• @AlexandreVaillancourt Do you mean if it is 2D or 3D? It's a 2D plaformer. – Caspert Mar 18 '15 at 19:42
• I have update the question. – Caspert 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;
}

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;
}

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";

• 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. – Caspert Mar 18 '15 at 21:26