# Waypoints and constant/variable speed problems?

Discussion in 'Scripting' started by Greg-Bassett, Oct 28, 2009.

1. ### Greg-Bassett

Joined:
Jul 28, 2009
Posts:
628
Hi all,

Basically I have my waypoints all setup and working, however my gameobject slows down as it reaches a waypoint, this means that my gameobject does not travel at a constant speed around all my waypoints.

I have read lots of forum topics on this subject, and I have tried a fair few waypoint implementations to get this to work, I did manage to get the gameobject to travel at a constant speed using Sam at FPS waypoint solution.

http://forum.unity3d.com/viewtopic.php?t=31412

However, I need my waypoint solution to work with a player controlled variable speed gameobject.

And Sam's example calculates the waypoint bezier curve based on time to complete the waypoints layout, prior to moving the gameobject.

I have had this working using Darkbasic Professional, see video below:
http://www.alabsoft.com/vSlot/vSlot - Work in progress/vSlot - Work in progress.html

However, I want to code this project in Unity now, as Unity is so much more powerful, and with cross-browser support etc.

In Darkbasic Professinal there is a command called CurveAngle.

Function CurveAngle(fA As Single, fDa As Single, fSp As Single) As Single

This command will return an auto-interpolated angle based on a given speed. This command will gradually move a number from its current value to a destination value at a certain speed.

I have found a similar command in the MathFX class from the Unify Wiki called Clerp.

But I cannot get it to work? here is my pseudo code, I know the transform.eulerAngles.y does not work? all I want to do is get the current y angle of the gameobject that my script is attached too.

Code (csharp):
1.
2. if(Vector3.Distance(transform.position,waypoints[currentWaypoint])<=damping) {
3.   //Debug.Log("Collided with waypoint");
4.   currentWaypoint++;
6. }
7.
8. // Get players current/old y angle
9. oldangle = transform.eulerAngles.y;
10.
11. // Point player in direction of current waypoint
13.
14. // Get players new y angle
15. newangle = transform.eulerAngles.y;
16.
17. // Now interpolate (create a smooth curve) the angle based on the speed and new and old angles
18. //finalangle = Mathfx.Clerp(oldangle, newangle, speed);
19.
20. // Rotate player
21. transform.eulerAngles = Vector3(0, finalangle, 0);
22.
23. // Move player forwards
24. transform.Translate(0, 0, speed * Time.deltaTime);
25.
26.
Here are some screenshots of my app in Unity.

This shows how the layout is constructed at runtime using Instantiate command, and the placement of the waypoints for each lane.

This shows the Hierarchy view with the cloned track sections.

This final image shows the layout with the waypoints hidden.

I have big plans for this project, multi-player, huge layouts, fastest lap competitions etc, etc, so any help with getting the basics working will be greatly appreciated!

[/img]

afvbmp likes this.
2. ### andeeeee

Joined:
Jul 19, 2005
Posts:
8,768
I've attached a Bezier/spline library script. It is still not finished, but I think it might help you out here. There's a class defined in it called CRSpline (ie, Catmull-Rom spline). This basically takes any number of waypoints and interpolates a smooth curve between them. This is mostly pretty straightforward but for one thing. Catmull-Rom splines actually have an "invisible" extra control point at the start and another at the end of the curve. This is to control the speed and direction of the curve at the start and the end of the interpolation. To create a cyclic track, you will need to set the first point of the spline to be one waypoint behind the start point and the last point in of the spline to be one beyond the finish, if you get what I mean.

This is by no means foolproof, but it should help reduce discontinuities in speed going from one track section to the next. The main other problem with speed is when waypoints are not evenly spaced. There is a GizmoDraw function in the CRSpline class that draws the curve along with a velocity vector. As you increase its parameter from 0 to 1, the velocity vector will move along the curve, showing you the velocity of the curve at that point (ie, the length of the line). This should help you diagnose where speed changes are happening and suggest where the waypoints need to be closer together or farther apart.

As I said, not entirely foolproof - please ask again if you have any trouble with this. I'll "launch" this library properly soon, when the missing functionality is in place.

#### Attached Files:

• ###### \$curve_443.cs
File size:
3.4 KB
Views:
5,913
oferei likes this.

Joined:
Jul 28, 2009
Posts:
628

4. ### Neodrop

Joined:
Oct 24, 2008
Posts:
1,359
andeeee, did you improve your code?
Can I use it in my Antares Project ?

5. ### andeeeee

Joined:
Jul 19, 2005
Posts:
8,768
It works OK as it is. I think my intention at the time was to add a natural spline too, but the existing code has been used quite a few times and seems to be OK.

6. ### Neodrop

Joined:
Oct 24, 2008
Posts:
1,359
I have splines too in my Antares project, but other type.
Can I use your code (with your credits) in my public open source project ?

7. ### andeeeee

Joined:
Jul 19, 2005
Posts:
8,768
It's public domain and I wrote it while working for Unity, so no credit required ;-)

8. ### Neodrop

Joined:
Oct 24, 2008
Posts:
1,359
Ok. Thank you.

Joined:
Jan 27, 2009
Posts:
3,732
Awesome, thank you Andee !

10. ### spanni87

Joined:
Mar 20, 2011
Posts:
8
I have 4 waypoints represented by the green arrows where I want the target to loop through these waypoints. The code that I used works fine i suppose but the problem is that when the target reaches the waypoints, it sticks to them as if the waypoint is holding the target and at a certain point the target is released and goes to the next waypoint.

anybody knows what's the problem? Thanks in advance

I also provided a link where I recorded my problem.

CODE:

var waypoint : Transform[];
var speed : float = 5000;
private var currentWaypoint: int;
var loop : boolean = true;

function Awake(){
waypoint[0] = transform;
}

function Update () {
if(currentWaypoint < waypoint.length){
var target : Vector3 = waypoint[currentWaypoint].position;
var moveDirection : Vector3 = target - transform.position;

var velocity = rigidbody.velocity;
if(moveDirection.magnitude < 1){
currentWaypoint++;
}
else{
velocity = moveDirection.normalized * speed;
}
}
else{
if(loop){
currentWaypoint=0;
}
else{
velocity = Vector3.zero;
}
}

rigidbody.velocity = velocity;

}

11. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
Hi Andy (or anyone)

I'm using this script to draw curves and it works really well, thanks. I just want to know how can I get the yValue on the curve based on the xPosition of one of my gameobjects? Tjis object is a time line and it loops from -10 to 10 on the x axis. I just need to find the yValue of the curve at any given point.

12. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
anyone that can shed some light?

### Digital Ape

Joined:
Apr 11, 2010
Posts:
29,723
I remember this stuff back when I was doing a zuma clone. The solution I used was incredibly simple:

1. after setting up splines in my editor, I would generate a linear array of points.

2. to create the array you traverse the spline as you normally do, however you only add a point to the array when DISTANCE between the current position and the last sample point is greater than n.

3. then you have an array of points each perfectly spaced apart.

4. then you use Mathf.Lerp() to go between, and use only the time parameter to travel.

x = lerp (prevpos, newpos, position)

- when position >1 you add one to prevpos and newpos, and subtract 1 from position.

Thats all there is to it for constant speed, thats how I did it. It also solves issues of missing waypoints and so on.

14. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
Thanks Hippo

I'm just a bit unclear about point 2 that you mentioned? Do you mean that I shoudl modify the way that I'm currently adding the points to my array so that the x values are evenly spaced? If so, I'm not sure how I'm going to achieve that...

15. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
I just tried to take sample points of the curve, but that does not work., Man, if I could test some collider with the line renderer and get the x value at a point, that might even work - so frustrating...

16. ### jeewanthasas

Joined:
Sep 8, 2011
Posts:
13
Hi,

If any one involved with mouse/ touch dragged-path following after releasing the mouse button or touch control (NOT following the mouse point) in a game like Air Traffic Controller/ Hurbour Master, plase assist me to control the speed of the object movement.

In my current script the mouse dragged path is followed by player object but the moving speed depends on the mouse-dragged/ touch dragged-speed. I just need to move the object in a constant speed.

I've attached the current script and please simply download the script and attached it to a game object and set smooth value to a value like 1000. It's works...!. But the object movement speed is relative to the mouse dragged speed/ touch-dragged speed.

Please assist me to move the object in a constant speed. It should not depend on the dragging speed.

Cheers....

Regards,
Jeewanthasas

File size:
3.7 KB
Views:
1,401
17. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
I wish I could help, but I have not even solved my problem - i've been ignoring it for the last month doing other stuff

18. ### jeewanthasas

Joined:
Sep 8, 2011
Posts:
13
Hi,

Thanks chubbspet, I could solve the issue and if anyone interested in the solution I would love to assist them.

Regards,

19. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
I will be very interrested!

20. ### Euro3d

Joined:
Oct 25, 2011
Posts:
11
Hello,

thx for the great spline class, it works great!!

As you mentioned andeeee, the speed along the spline depends on the control points distance. In my scene I using this spline class to generate a camera path. The problem here is that I want to design a constant movement speed along this spline. How do I do this? I tried taking the velocity's magnitude and calculating it with my parameter t:

void Update()
{
float magnitude = crSpline.Velocity((speed * Time.time) % 1.0f).magnitude;
renderingCamera.transform.position = crSpline.Interp((speed * Time.time / magnitude) % 1.0f);
}

but this does not work, any suggestions guys??

21. ### chubbspet

Joined:
Feb 18, 2010
Posts:
1,220
I'm also still looking for a solution for the constant speed issue.

22. ### TiG

Joined:
Feb 28, 2011
Posts:
311
While answering to another similar topic, I have noticed this one and realized that constant speed is a problem among many. I believe doing it while controlling the transform.position each frame is easy and can be done by the method hippocoder describes. However doing it with rigidbodies that are controlled with forces is a whole different topic. If anyone wants a tip, search the methods of control engineering. If you want me to solve it for your project, PM me.

This problem of precise control of speed or another variable in a mechanical system is frequently faced by engineers of all sorts, and there are many techniques developed to solve them. Any they can easily be adapted to Unity.

23. ### BobBobson108

Joined:
Mar 13, 2008
Posts:
57
Hi all, I was wondering how I could convert this to a Cubic Bezier, so that the path is smoother and does not pass through the points. I've been to a lot of different places on the web but they all talk about multiplying matrices by the Vector3 and I don't think I know enough to do this on my own (because I keep getting a Vector3 of 0,0,0). I'm using iTween right now but there's no built in class that allows points to form a Cubic Bezier instead of a Catmull-Rom spline. Any help and/or links is much appreciated.

Thanks!!
~Jake

24. ### andeeeee

Joined:
Jul 19, 2005
Posts:
8,768
There are classes for quadratic and cubic Bezier curves in the library I posted. And fear not - no matrices required! ;-)

25. ### BobBobson108

Joined:
Mar 13, 2008
Posts:
57
Thank you VERY much!! I followed this link from the source code inside iTween, so I don't have the full library I guess Thanks again!!

26. ### Demigiant

Joined:
Jan 27, 2011
Posts:
3,242
Hey Andeeee, I just wanted to thank you for the CRSpline class: I'm using it in my tween engine (HOTween) and it works perfectly (with some addition to achieve constant speed and such).

And sorry if I'm late: I credited you on the website, but I forgot to come and say thank you here

27. ### akasurreal

Joined:
Jul 17, 2009
Posts:
442
Wow, so glad I found this thread, thanks a ton, this works perfectly for what I needed!

28. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
Thanks for the great script Andeeee, I've added a variety of easing in/out functions to it and created a wrapper that uses the Cubic and Quad functions for an array that has less than 5 values). This seems to work pretty well. I've also added a function to traverse the path at constant speed.

Anyone interested can download my version from my blog, which you can find here.

Last edited: Apr 7, 2012
r618 likes this.
29. ### yahodahan

Joined:
Apr 26, 2009
Posts:
1,382
Hi Whydoidoit, thanks for the great update! I am a little confused though, trying to get it to work- do I need to use a C# script to access it? Or can I do so simply from Javascript? In your example you show: "Spline.Interp(myPathObject.GetComponentsInChildren<Transform>(), time);"

I am not familiar with the "<Transform>()", though I assume it is the same as "(Transform)" in JS?

Would you mind giving more examples of how to use this? Thank you much!

30. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
Hi there, firstly, sorry the initial version got uploaded from an old project by accident and didn't work!

Next, so long as the package is installed under Plugins (it is by default) you can use it from JavaScript. The following script will follow a path taking 20 seconds to do so.

#pragma strict

var pathPoints : Transform[];

var t : float;

function Update () {
transform.position = Spline.InterpConstantSpeed(pathPoints, t, EasingType.Sine, true, true);
t += Time.deltaTime/20;
}

31. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
It's fixed now

32. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
I've also added my function that enables a path to be followed using a maximum speed that enables a different kind of constant speed path and added extra documentation that includes Javascript.

Last edited: Apr 7, 2012
33. ### yahodahan

Joined:
Apr 26, 2009
Posts:
1,382
Thanks much!

This is really going to be a great help

34. ### yahodahan

Joined:
Apr 26, 2009
Posts:
1,382
Just noticed, when using the "Spline.MoveOnPath" method, when the object reaches the final waypoint, it sends Unity into a non-recoverable loop. Yoiks! Definitely fixable from the end-user's point, but maybe easier to do from within the C# file?

Thanks again!

35. ### geno

Joined:
Mar 11, 2012
Posts:
18
Thanks for sharing this, Whydoidoit!
Just FYI: the examples on your blog post seems to be outdated concerning the given number of parameters a function requires now.

36. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
Oops, serves me right for trying to pull code out of one project into another. Think that's fixed now.

37. ### whydoidoit

Joined:
Mar 12, 2012
Posts:
365
I think the documentation is up to date. Most of the routines have lots of optional parameters. The odd one is MoveOnPath which has two versions, and optional parameters I wrote that doc recently looking at the code so I hope it's right! The examples certainly all work in my test project... I know MonoDevelop tends not to indicate which parameters have default values - I have a tendency to make most parameters take sensible defaults (so for instance the default easing type is Linear - i.e. no easing at all). So for example you can still call Interp or InterpConstantSpeed with two parameters - the rest have sensible defaults.

Last edited: Apr 7, 2012
38. ### huogeCarlos

Joined:
Apr 23, 2014
Posts:
1
Thank you for andeeeee 's help .But i still have a problem.How can i get the small point(every small point on the path) corresponding time? or the big point(created by myself as the path Node) corresponding time? Similar as the Fuction PointOnPath() ,can it Get back the point corresponding time?

39. ### afvbmp

Joined:
Sep 10, 2014
Posts:
1
excellent,This is really going to be a great help

40. ### Gooseman_1977

Joined:
Aug 15, 2013
Posts:
89
If you are feeling rich, you should check out this plugin.
https://www.assetstore.unity3d.com/en/#!/content/2506

It has a wonderful waypoint/spline functionality and comes with full source code. I picked it up and was able to make modifications to it quite easily for my racing game.