Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
3
Question by straydogstrut · Mar 10, 2010 at 04:30 PM · transformlerpwaypoint

Move an object through a set of positions

Okay, I know this should be much more straightforward than I'm finding but my brain is mush today, sorry.

In the level i'm making I want characters to patrol back and forth over an area repeatedly - specifically travel through a set of waypoints. I've been reading up on Angry Ant's Path and Aron Granberg's A* Pathfinding for a future project, but for this I don't need actual pathfinding since the characters don't have to go anywhere other than along their set path. They will have a vision cone or torchlight that, when it touches the player, will reset the players position. Basically a really simple stealth game.

Last year I modified the SeekSteer script on the wiki to have a character move along a set of waypoints but it was a bit of a rushed job and it had some problems. I'm returning to it now and starting from scratch. I'm using the Lerp function as described in this post to move my object to the new position and i've combined that script with my waypoint one (it looks nothing like SeekSteer now by the way).

I rewrote my old script since I had the unwanted effect of easing in and out of positions - where that came from I don't know - but aside from that it worked. I'm using the same code here, the only real difference is the method to move the character and the old script had a radius for each waypoint. There are currently 3 transforms in the waypoints array to make an 'L' shape. But after the character reaches the first waypoint I get an Index Out of Range error.

As far as I can tell, the part where the targetwaypoint variable is being incremented is suspect but this wasn't a problem in the other script despite being in the Update function.

// array to hold waypoint locations var waypoints : Transform[];

// variable to control time taken to travel between points var duration : float = 1.0;

private var startPoint : Vector3; private var endPoint : Vector3; private var startTime : float;

// the array index number of the current target waypoint private var targetwaypoint : int;

function Start() { startPoint = transform.position; startTime = Time.time;

 if(waypoints.Length <= 0){
 Debug.Log("No waypoints found");
 enabled = false;
 }

 targetwaypoint = 0;
 endPoint = waypoints[targetwaypoint].position;
 }

function Update () {

transform.position = Vector3.Lerp(startPoint, endPoint, (Time.time - startTime) / duration);

if(transform.position == endPoint){

 targetwaypoint++;

 endPoint = waypoints[targetwaypoint].position;

     // if this new target is the last item in the array
     if(targetwaypoint>=waypoints.Length){

         targetwaypoint = 0;
     }
 }

}

Comment
Add comment · Show 1
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 straydogstrut · Mar 10, 2010 at 04:35 PM 0
Share

I've just read through my post again and realised I don't actually change the value of startPoint at any point after it is initially set. Adding startPoint = transform.position; into the Update function has slowed it down enough that I can see all the waypoints are being used but after the first one it's super fast and I still get an Index Out of Range error at the end. Am I going about this completely the wrong way?

3 Replies

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

Answer by duck · Mar 10, 2010 at 05:09 PM

I think your "super fast" problem is occuring because you're not resetting the startTime variable when you increment the targetwaypoint counter. This means that for every transition after the first one, the duration has already elapsed.

As for the 'index out of range' error, I would guess that's occuring because you're assigning the new endPoint before you check whether the targetwaypoint variable should be wrapped back to zero.

Move the line:

endPoint = waypoints[targetwaypoint].position;

...to after the check where you test if it's the last item in the array. (remember, array access is zero-indexed, so if targetwaypoint == waypoints.Length, then targetwaypoint isn't a valid index!

(If your array is 8 items long, the first item is at position zero, and the last item is at position 7!)

Also, you might be interested in a neat way of "wrapping" your integer index counter using the modulus operator.

Also, I've moved the Lerp interpolation value to a separate variable for shorter line length, and fixed the indentation :)

So, with these fixes, your could might look like this.

// array to hold waypoint locations var waypoints : Transform[];

// variable to control time taken to travel between points var duration : float = 1.0;

private var startPoint : Vector3; private var endPoint : Vector3; private var startTime : float;

// the array index number of the current target waypoint private var targetwaypoint : int;

function Start() {

 startPoint = transform.position;
 startTime = Time.time;

 if(waypoints.Length <= 0){
     Debug.Log("No waypoints found");
     enabled = false;
 }

 targetwaypoint = 0;
 endPoint = waypoints[targetwaypoint].position;

}

function Update () {

 var i = (Time.time - startTime) / duration;
 transform.position = Vector3.Lerp(startPoint, endPoint, i);

 if(i >= 1){

     startTime = Time.time;

     // increment and wrap the target waypoint index
     targetwaypoint++;
     targetwaypoint = targetwaypoint % waypoints.Length;

     // assign the new lerp waypoints
     startPoint = endPoint;
     endPoint = waypoints[targetwaypoint].position;

 }

}

Comment
Add comment · Show 7 · 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 straydogstrut · Mar 10, 2010 at 08:17 PM 0
Share

Thanks for the detailed response Duck=) I knew about arrays being zero indexed but didn't see the flaw in my logic, and yeah, I should have noticed the problems with startTime and endPoint. I looked at the modulus operator you mentioned and, while I understand what it does with two values, i'm not sure I understand what it's doing here (that and I get an unexpected token error when using it). I'm assu$$anonymous$$g the result wraps around back to '0' each time? How would I write this without the shorthand? Ultimately I want the character to move through the waypoints in reverse when they reach the end.

avatar image straydogstrut · Mar 10, 2010 at 08:22 PM 0
Share

I was a bit confused at first with the line if(i >= 1) but am I right in thinking that this is doing a similar thing as my line if(transform.position == endPoint) since the '1' is the end value returned by the Lerp function (or at least, as I understand it, the value of i varies between 0 and 1)? Is there any benefit to writing it this way ins$$anonymous$$d apart from shorter code?

I also couldn't assign the temporary variable 'i' like you have - in the end I had to create a variable for it - as it kept asking for a semicolon.

avatar image duck ♦♦ · Mar 10, 2010 at 08:27 PM 0
Share

Oh, yes - the i>=1 is mainly for shorter code, but it's also generally good practice to not rely on comparing floats (or structs which contain floats) for equality, because of floating point imprecision problems: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

avatar image duck ♦♦ · Mar 10, 2010 at 08:28 PM 0
Share

I'm surprised that %= doesn't work - it seems to be yet another thing missing from the JS syntax. Basically: "a %= b" is the same as "a = a % b", in the same way as "a += b" is the same as "a = a + b". And the "float i" thing was a result of me accidentally mixing c# and JS. sorry! (both have been fixed in the code now)

avatar image straydogstrut · Mar 10, 2010 at 09:05 PM 0
Share

Thanks Duck, that fixes the errors and i'm getting there with understanding % (maths was never my strong point - back to school I think!) Cheers.

Show more comments
avatar image
1

Answer by SwapnilRane · Aug 01, 2016 at 02:19 PM

Use this code add as many waypoint you want.

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

[RequireComponent(typeof(Rigidbody2D))] public class SquareMovement : MonoBehaviour {

 [SerializeField]
 private List<Transform> wayPoints;

 public float speed = 10f;

 private Transform target;
 private int waypointIndex = 0;

 // Use this for initialization
 void Start ()
 {
     target = wayPoints[0];
 }
 
 // Update is called once per frame
 void Update ()
 {
     Movement();
 }

 //methode which decide which axis to move
 void Movement()
 {
     Vector3 dir = target.position - transform.position;
     transform.Translate(dir.normalized * speed * Time.deltaTime , Space.World);

     if (Vector3.Distance(transform.position, target.position) <= 0.2f)
     {
         GetNextWayPoint();
     }

 }

 void GetNextWayPoint()
 {
     if (waypointIndex >= wayPoints.Count - 1)
     {
         waypointIndex = 0;
     }
     else
     {
         waypointIndex++;
     }

     target = wayPoints[waypointIndex];
 }


}

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
0

Answer by straydogstrut · Mar 11, 2010 at 02:36 AM

I've been looking into stepping back through the array when I reach the end. I didn't achieve that yet (seemed to have become a bit distracted in the process!) but I've modified my code quite a bit so thought I would post it here as an alternate solution.

Now i'm using a normal Javascript array rather than an in-built one (although i've read in-built ones are faster). This approach allows me to use the Shift and Add functions to achieve the same effect as Duck's modulus approach (as far as I can tell) and also means that the array is resizeable. Since Javascript arrays can't be modified from the editor i've added some script to automatically add the waypoints to the array at initialisation (much more efficient than dragging them into the editor).

Currently I have an empty object called waypoints with child cubes for the individual waypoints. The script is attached to the NPC and so has to find the waypoint object's children (took me a while to get that working!). I'd be happy to hear and comments/criticism, and thanks once again to you Duck for your help.

// array to hold waypoint locations var waypoints = new Array();

// variable to control time taken to travel between points var duration : float = 1.0;

private var startPoint : Vector3; private var endPoint : Vector3; private var startTime : float;

private var wp : Transform;

// the array index number of the current target waypoint private var targetwaypoint : int;

function Start() { startPoint = transform.position; startTime = Time.time;

 // store a reference to the transform of the waypoints object
 wp = GameObject.Find("waypoints").transform;

 // for each of the child objects of the waypoints object
 for (var child : Transform in wp) {

     // add them to the waypoints array
     waypoints.Push(child);
 }   


 if(waypoints.length &lt;= 0){
     Debug.Log("No waypoints found");
     enabled = false;
 }

 targetwaypoint = 0;

 // set the initial end point to the first item in the array
 endPoint = waypoints[targetwaypoint].position;
 }

function Update () {

 var i = (Time.time - startTime) / duration;
 transform.position = Vector3.Lerp(startPoint, endPoint, i);

 // if we have reached the target
 if(i &gt;= 1){

     // store the current time as the new start time
     startTime = Time.time;

     // store the value of the current item in the array and remove it from the array
     currentwaypoint = waypoints.Shift();
     // add the previously removed item to the end of the array
     waypoints.Add(currentwaypoint);


     // set our start point to our current position
     startPoint = endPoint;


     //set our new endpoint to the position of the new target waypoint
     endPoint = waypoints[targetwaypoint].position;

 }


}

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

object pauses at the each way points for a vary short time 1 Answer

Making a Lerp + Collisions waypoint system? 2 Answers

Vector3.Lerp completing before t = 1? 2 Answers

Determine transform.position of location between two waypoints on bezier path 0 Answers

Constant total time over multiple Lerp functions 4 Answers


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