Vector3 movement problems

I have a problem when moving a Vector3 and detecting when it hits a certain position.
The problem with this example code

Vector3 myVector = new Vector3();
Vector3 targetVector = new Vector3(20, 0, 0);

void Update()
{
	myVector += new Vector3(5, 0, 0) * Time.deltaTime;
	if(myVector == targetVector)
	{
	  //do something
	}
}

is that the if-condition will only trigger sometimes, or almost never. I have tried this:

myVector = new Vector3(Mathf.Round(myVector.x * 10) / 10, Mathf.Round(myVector.y * 10) / 10, Mathf.Round(myVector.z * 10) / 10);

It works with a higher success rate, but still not as I wish.

Thanks in advance,

That’s not the best practice, it’s much better to use something like path-definition an follow path scripts.

There is very clear and well explained video tutorial Creating 2D Games in Unity 4.5 #4 - Moving Platforms - YouTube

The most valuable advantage of this method - You (or Your level designer) can do it easily in Unity editor without any scripting.

So I’ve add my scripts below. You can easily modify them and trigger events on reaching the key points of the path. Take look on MaxDistanceToGoal parameter in follow path script. The main algorithm to calculate distances between to points, and actually the answer to your question - is comparison of squared vector magnitudes:

float MaxDistanceToGoal = .1f;
...
var distanceSquared = (transform.position - _currentPoint.Current.position).magnitude;
if (distanceSquared < MaxDistanceToGoal * MaxDistanceToGoal) {
    // do something here
    YouHaveReachedTheTarget();
}

In addition to features that implemented in tutorial:

  • Construction of path manually in Unity editor - no hard code.
  • Following types: MovingTowards and Lerp.
  • Visual interpretation of paths in Unity editor.

i implemented some more logics, such as:

  • Two types of path: Circle and “Ping-pong”.
  • Reversing scale on X-axis (we did a 2D-platformer, so it was enough for our purposes… nevertheless You can implement reversing for other axis).
  • Destroying moving objects (or their parents) on stop (it’s suitable for example for static canon that is making shots in some restricted area).
  • Countdown counter for iterations (-1 endless iteration).

Maybe it’s off-topic but I think that You should take a look deeply on this stuff.

Path definition script:

using System;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;

public class PathDefenition : MonoBehaviour {

	public Transform[] Points;

	public enum PathType {
		PingPong,
		Circle
	}
	public PathType Type = PathType.PingPong;

	public IEnumerator<Transform> GetPathEnumerator()
	{
		if (Points == null || Points.Length < 1)
			yield break;

		var direction = 1;
		var index = 0;
		while (true) {
			yield return Points[index];

			if (Points.Length == 1)
				continue;

			if (Type == PathType.PingPong) {
				if (index <= 0)
					direction = 1;
				else if (index >= Points.Length - 1)
					direction = -1;
				index = index + direction;
			}
			else if (Type == PathType.Circle)
				if (index == Points.Length - 1)
					index = 0;
				else
					index += 1;
		}
	}

	public void OnDrawGizmos() {
		if (Points == null || Points.Length < 2)
			return;

		for (var i = 1; i < Points.Length; i++)
			Gizmos.DrawLine (Points [i - 1].position, Points *.position);*
  •  if (Type == PathType.Circle)*
    
  •  	Gizmos.DrawLine (Points [0].position, Points [Points.Length - 1].position);*
    
  • }*
    }
    Follow path script:
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Collections;

public class FollowPath : MonoBehaviour {

  • public enum FollowType {*

  •  MoveTowards,*
    
  •  Lerp*
    
  • }*

  • public FollowType Type = FollowType.MoveTowards;*

  • public PathDefenition Path;*

  • public float Speed = 1;*

  • public float MaxDistanceToGoal = .1f;*

  • public bool reversexScale;*

  • public bool AlwaysFromStart = false;*

  • public bool DestroyOnStop = false;*

  • public bool DestroyParentOnStop = false;*

  • public int Delay = 1;*

  • public int Repeat = -1;*

  • private bool stop = false;*

  • private bool temp_stop = false;*

  • private IEnumerator _currentPoint;*

  • private Vector3 old_position;*

  • public bool IsStop() {*

  •  return stop;*
    
  • }*

  • public bool IsTempStop() {*

  •  return temp_stop;*
    
  • }*

  • void MoveNextPointHandler() {*

  •  _currentPoint.MoveNext ();*
    
  •  if (*
    
  •  	(_currentPoint.Current.position.x - old_position.x > 0 && transform.localScale.x < 0 && reversexScale) ||*
    
  •  	(_currentPoint.Current.position.x - old_position.x < 0 && transform.localScale.x > 0 && reversexScale)*
    
  •  ) {*
    

_ transform.localScale = new Vector3 (transform.localScale.x * -1, transform.localScale.y, transform.localScale.z);_

  •  }*
    
  •  old_position = _currentPoint.Current.position;*
    
  • }*

  • bool MoveNextPoint() {*

  •  if (Repeat > 0) {*
    
  •  	Repeat -= 1;*
    
  •  }*
    
  •  if (Repeat >= 0) {*
    
  •  	if (Repeat == 0) {*
    
  •  		return false;	*
    
  •  	}*
    
  •  }*
    
  •  MoveNextPointHandler();*
    
  •  return true;*
    
  • }*

  • void Start () {*

  •  if (Path == null) {*
    
  •  	Debug.LogError ("Path cannot be null", gameObject);*
    
  •  	return;*
    
  •  }*
    
  •  _currentPoint = Path.GetPathEnumerator ();*
    
  •  _currentPoint.MoveNext ();*
    
  •  old_position = _currentPoint.Current.position;*
    
  •  if (_currentPoint.Current == null)*
    
  •  	return;*
    
  •  transform.position = _currentPoint.Current.position;*
    
  •  MoveNextPointHandler ();*
    
  • }*

  • void Update () {*

  •  if (!stop) {*
    
  •  	if (!temp_stop) {*
    
  •  		if (_currentPoint == null || _currentPoint.Current == null)*
    
  •  			return;*
    
  •  		if (Type == FollowType.MoveTowards)*
    

transform.position = Vector3.MoveTowards (transform.position, _currentPoint.Current.position, Time.deltaTime * Speed);

  •  		else if (Type == FollowType.Lerp)*
    

transform.position = Vector3.Lerp (transform.position, _currentPoint.Current.position, Time.deltaTime * Speed);

  •  		var distanceSquared = (transform.position - _currentPoint.Current.position).magnitude;*
    

_ if (distanceSquared < MaxDistanceToGoal * MaxDistanceToGoal) {_

  •  			if (AlwaysFromStart) {*
    
  •  				StartCoroutine (WaitForAnotherRunCoroutine ());*
    
  •  			} else {*
    
  •  				StartCoroutine (WaitForDelayCoroutine());*
    
  •  			}*
    
  •  		}*
    
  •  	}*
    
  •  }*
    
  •  else {*
    
  •  	if (transform.parent.gameObject && DestroyParentOnStop){*
    
  •  		Destroy(transform.parent.gameObject);*
    
  •  	} else if (DestroyOnStop){*
    
  •  		Destroy(transform.gameObject);*
    
  •  	}*
    
  •  }*
    
  • }*

  • void stopAnimation() {*

  •  if (gameObject.GetComponent<Animation>() != null) {*
    
  •  	gameObject.GetComponent<Animation>().Stop();*
    
  •  }*
    
  • }*

  • IEnumerator WaitForAnotherRunCoroutine() {*

  •  temp_stop = true;*
    
  •  transform.GetComponent<Renderer>().enabled = false;*
    
  •  MoveNextPointHandler();*
    
  •  transform.position = _currentPoint.Current.position;*
    
  •  stop = !MoveNextPoint ();*
    
  •  if (Delay > 0) {*
    
  •  	stopAnimation();*
    
  •  	yield return new WaitForSeconds(Delay);*
    
  •  	stopAnimation();*
    
  •  }*
    
  •  transform.GetComponent<Renderer>().enabled = true;*
    
  •  temp_stop = false;*
    
  • }*

  • IEnumerator WaitForDelayCoroutine() {*

  •  temp_stop = true;*
    
  •  stop = !MoveNextPoint ();*
    
  •  if (Delay > 0) {*
    
  •  	yield return new WaitForSeconds(Delay);*
    
  •  }*
    
  •  if (!stop) {*
    
  •  	temp_stop = false;*
    
  •  }*
    
  •  yield break;*
    
  • }*

}
Hope that it will help. Have fun!

The problem is that you are checking if its the same, but it most likely never be the same, will go over and move infinitely.

You might want to check or lerp or movetowards.

public float speed = 5f;
private Vector3 target = new Vector3(20, 0, 0);

private void Update(){

    float step = speed * Time.deltaTime;
    transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
}

Try putting this in your Update function

Debug.Log (myVector.x);

And seeing if it ever equals 20. My guess is that you can do

if (myVector.x >= targetVector.x)
{
    //Reached point
}

What are you trying to do with this code?

-Chill

Since you’re adding unpredictable floating point values to position vector, chances are it will never get exactly to the position you’re comparing it to. A better approach is to see if it gets really close to that position. You can do that by comparing the distance between the two positions using Vector3.Distance.

if (Vector3.Distance(myVector, targetVector) < 0.01f)
{
   // the positions are really close
}

Depending on the maximum possible speed, you may need to play around with the 0.01 value. Faster max speeds would require a larger threshold.

Another option (that someone else just answered) if you know a specific target position is to just move the object toward that position using some sort of lerp function. You know when it’s done that it will be at that position - no comparisons necessary.

Have you tried using Vector3.Distance. You set a float to the 2 Vector3s and in an if statement if (distance <= 0.5f) {Do Something} or something like that. That might work better.