I am trying to move an enemy character in a 2d game along the x-axis between the positions (-4,0) and (4,0). Currently, the object moves to right side indefinitely not returning to (-4,0) as intended.
Following is the script I have tried to write (no error message appears in unity):
As for the code at the link, any code by @Eric5h5 is worth looking at and learning from. And I applaud you going out and finding a solution for yourself. But before you ‘abandon’ this question, you might puzzle out why your code did not work. There are several significant problems.
Never compare floating point numbers with ‘==’. Floating point numbers are imprecise, so your adding 0.1f over multiple frames might yield a value of 4.00000000000001…and this value would fail the comparison. When you can, use inequality. For example here, you could use ‘>=’. Sometimes you need something more exact. Mathf.Approximately() can be helpful.
Your logic does not allow the object to reverse. That is, if line 3 were true, you would back up for a single frame, but then line 10 would be true, so you would head forward, which would make line line 3 true…and so on.
While it is not the reason for your failure, when moving something through the Transform, you want to use ‘Time.deltaTime’. Not every frame take the same amount of time, so using a fixed value will make your code run at different speeds on different devices, plus it may jitter as the frame rate changes.
So here is a quick rewrite of your code:
using UnityEngine;
using System.Collections;
public class Example1 : MonoBehaviour {
private bool dirRight = true;
public float speed = 2.0f;
void Update () {
if (dirRight)
transform.Translate (Vector2.right * speed * Time.deltaTime);
else
transform.Translate (-Vector2.right * speed * Time.deltaTime);
if(transform.position.x >= 4.0f) {
dirRight = false;
}
if(transform.position.x <= -4) {
dirRight = true;
}
}
}
In Unity there is often many want to accomplish the same task. Here is another method of moving the block back and forth between two positions. It used Mathf.PingPong().
public class Example2 : MonoBehaviour {
private Vector3 pos1 = new Vector3(-4,0,0);
private Vector3 pos2 = new Vector3(4,0,0);
public float speed = 1.0f;
void Update() {
transform.position = Vector3.Lerp (pos1, pos2, Mathf.PingPong(Time.time*speed, 1.0f));
}
}
And yet one more solution using Mathf.Sin(). This version will feel more natural…more line a pendulum swinging between two positions. It is the same as the previous example except with one line changed:
public class Example3 : MonoBehaviour {
private Vector3 pos1 = new Vector3(-4,0,0);
private Vector3 pos2 = new Vector3(4,0,0);
public float speed = 1.0f;
void Update() {
transform.position = Vector3.Lerp (pos1, pos2, (Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f);
}
}
Wow! Thanks for your very informative response Robert! It definitely helps a lot!
public Transform pointA;
public Transform pointB;
public bool isRight = true;
public float speed = 0.3f;
private Vector3 pointAPosition;
private Vector3 pointBPosition;
// Use this for initialization
void Start ()
{
pointAPosition = new Vector3 (pointA.position.x, 0, 0);
pointBPosition = new Vector3 (pointB.position.x, 0, 0);
}
// Update is called once per frame
void Update ()
{
Vector3 thisPosition = new Vector3 (transform.position.x, 0, 0);
if (isRight) {
transform.position = Vector3.MoveTowards (transform.position, pointB.position, speed);
if (thisPosition.Equals (pointBPosition)) {
//Debug.Log ("Position b");
isRight = false;
}
} else {
transform.position = Vector3.MoveTowards (transform.position, pointA.position, speed);
if (thisPosition.Equals (pointAPosition)) {
//Debug.Log ("Position a");
isRight = true;
}
}
}
I just added this in update . This did the trick. Vector2 start = transform.position; start.x = 2 * Mathf.Sin(Time.time); // transform.position = start;
Wow! Thanks for your very informative response Robert! It definitely helps a lot!
– Ammar-AliThanks very much Robert, you helped me a lot!!
– NachoLarretaWow man. It's amazing. Thanks a ton.
– MusabbirThat's awesome @robertbu! Thanks for taking the time to post such a good explanation.
– akaCarboneI'm surprised that no one mentioned this: you should not use Time.time in an Update() call, this is bad practice.
– neo-mashiro