Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Benjamin Minixhofer · Jun 18, 2015 at 07:14 PM · unity 5vector3

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,

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Dave-Carlile · Jun 18, 2015 at 09:28 PM

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.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by Doomatel · Jun 18, 2015 at 09:45 PM

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 https://www.youtube.com/watch?v=ZkGPoZOQE5Q

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 [i].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<Transform> _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!

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Dave-Carlile · Jun 18, 2015 at 09:48 PM 1
Share

$$anonymous$$ight be better for OP to start off a little slower and learn about Vectors and such before jumping into the deep end.

avatar image Benjamin Minixhofer · Jun 19, 2015 at 05:19 AM 0
Share

As Dave Carlile said, I would prefer starting off with simple vector movements. Thanks for your detailed answer tho! I will definately use it as a reference later on when facing similar problems.

avatar image
1

Answer by YoungDeveloper · Jun 18, 2015 at 09:14 PM

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

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by chrismkhill · Jun 18, 2015 at 11:08 PM

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

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benjamin Minixhofer · Jun 19, 2015 at 05:15 AM 0
Share

I use it for a snake-like movement algorithm. The first object can be controlled via up, down, left and right keys. $$anonymous$$y goal was that multiple GameObjects follow it and i tried to do that with a Vector3 that gets set at the turn position of the leading object so whenever a following object passes it, it turns in the appropriate direction. There could be an easier way to solve this but I am pretty new to unity and this was my first approach to the problem. So far i got along well with it, exept of the problem mentioned here.

avatar image
0

Answer by tyxman · Jun 18, 2015 at 09:44 PM

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.

http://docs.unity3d.com/ScriptReference/Vector3.Distance.html

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Pushing a ball in a direction -1 Answers

Vector3.distance is always returning 0 4 Answers

What is difference between local and global coord Vector3. 1 Answer

How to Clamp LookAt on the Y Axis 1 Answer

Rotating game object to movement direction 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges