Waypoints and constant/variable speed problems?

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

  1. Greg Bassett

    Greg Bassett

    Member

    Joined:
    Jul 28, 2009
    Messages:
    391
    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++;
    5.   currentHeading = waypoints[currentWaypoint];
    6. }
    7.  
    8. // Get players current/old y angle
    9. oldangle = transform.eulerAngles.y;
    10.    
    11. // Point player in direction of current waypoint
    12. //transform.LookAt(currentHeading);
    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.

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

    [​IMG]
    This shows the Hierarchy view with the cloned track sections.

    [​IMG]
    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]
  2. andeeeee

    andeeeee

    Unity Technologies

    Joined:
    Jul 19, 2005
    Messages:
    8,729
    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:

  3. Greg Bassett

    Greg Bassett

    Member

    Joined:
    Jul 28, 2009
    Messages:
    391
    Thanks for info, I will download and take a look.
  4. Neodrop

    Neodrop

    Member

    Joined:
    Oct 24, 2008
    Messages:
    1,342
    andeeee, did you improve your code?
    Can I use it in my Antares Project ?
  5. andeeeee

    andeeeee

    Unity Technologies

    Joined:
    Jul 19, 2005
    Messages:
    8,729
    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

    Neodrop

    Member

    Joined:
    Oct 24, 2008
    Messages:
    1,342
    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

    andeeeee

    Unity Technologies

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

    Neodrop

    Member

    Joined:
    Oct 24, 2008
    Messages:
    1,342
    Ok. Thank you.
  9. n0mad

    n0mad

    Member

    Joined:
    Jan 27, 2009
    Messages:
    3,731
    Awesome, thank you Andee ! :D
  10. spanni87

    spanni87

    New Member

    Joined:
    Mar 20, 2011
    Messages:
    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.

    http://www.youtube.com/watch?v=nrh34Cjf9qw

    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

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    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.

    Please help me with this urgent problem, thanks
  12. chubbspet

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    anyone that can shed some light?
  13. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    10,931
    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

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    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

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    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

    jeewanthasas

    New Member

    Joined:
    Sep 8, 2011
    Messages:
    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.

    Thank you in advance... :)
    Cheers....

    Regards,
    Jeewanthasas

    Attached Files:

  17. chubbspet

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    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

    jeewanthasas

    New Member

    Joined:
    Sep 8, 2011
    Messages:
    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

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    I will be very interrested!
  20. Euro3d

    Euro3d

    New Member

    Joined:
    Oct 25, 2011
    Messages:
    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

    chubbspet

    New Member

    Joined:
    Feb 18, 2010
    Messages:
    1,058
    I'm also still looking for a solution for the constant speed issue.
  22. TiG

    TiG

    Member

    Joined:
    Feb 28, 2011
    Messages:
    291
    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

    BobBobson108

    Member

    Joined:
    Mar 13, 2008
    Messages:
    41
    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

    andeeeee

    Unity Technologies

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

    BobBobson108

    Member

    Joined:
    Mar 13, 2008
    Messages:
    41
    Thank you VERY much!! :D I followed this link from the source code inside iTween, so I don't have the full library I guess :p Thanks again!!
  26. Izitmee

    Izitmee

    Member

    Joined:
    Jan 27, 2011
    Messages:
    2,345
    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 :p
  27. akasurreal

    akasurreal

    Member

    Joined:
    Jul 17, 2009
    Messages:
    423
    Wow, so glad I found this thread, thanks a ton, this works perfectly for what I needed!
  28. whydoidoit

    whydoidoit

    Member

    Joined:
    Mar 12, 2012
    Messages:
    367
    :) 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
  29. yahodahan

    yahodahan

    Member

    Joined:
    Apr 26, 2009
    Messages:
    1,232
    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

    whydoidoit

    Member

    Joined:
    Mar 12, 2012
    Messages:
    367
    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

    whydoidoit

    Member

    Joined:
    Mar 12, 2012
    Messages:
    367
    It's fixed now
  32. whydoidoit

    whydoidoit

    Member

    Joined:
    Mar 12, 2012
    Messages:
    367
    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

    yahodahan

    Member

    Joined:
    Apr 26, 2009
    Messages:
    1,232
    Thanks much!

    This is really going to be a great help :)
  34. yahodahan

    yahodahan

    Member

    Joined:
    Apr 26, 2009
    Messages:
    1,232
    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

    geno

    New Member

    Joined:
    Mar 11, 2012
    Messages:
    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

    whydoidoit

    Member

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

    whydoidoit

    Member

    Joined:
    Mar 12, 2012
    Messages:
    367
    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

    huogeCarlos

    New Member

    Joined:
    Apr 23, 2014
    Messages:
    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?