Search Unity

Creating curves based on Vector2's and velocitys

Discussion in 'Scripting' started by spec7or, Sep 18, 2014.

  1. spec7or

    spec7or

    Joined:
    Jan 11, 2014
    Posts:
    4
    Hello everyone,

    I am currently having difficulty wrapping my head around an issue concerning curves. I am attempting to create a curve based on a 2d grid. The player controls an object that has a potentialy changing forward velocity like an aircraft, when the player clicks and drags a new point on the grid the object will create a curve from the point it is at to the point click. However I am having difficulty determining the p1 and p2 points of a bezier curve. Sorry if this isnt exactly clear but I will provide an example of what I mean below.

    Player is a point (15,25) traveling on the y coordinate at 5 m/s.
    The point chosen is at (35, 50) traveling at 2 m/s on the x coordinate.

    So if I am using a cubic bezier curve it looks like p0 = 15,25; p1 = ?; p3 = ?; and p4 = 35, 50.
    How do I go about finding p1 and p3 with a differing velocity?
    And how do I then determine the length of said curve so I can calcuate the amount of realtime it should take between p0 and p1?

    Tldr;
    Attempting to create a curve between to points where velocity determines the p1 and p3 points.

    If there is an easier way to do this I'm open to suggestions.

    Thank you
     
  2. FlashMuller

    FlashMuller

    Joined:
    Sep 25, 2013
    Posts:
    451
    About your points: P0 is the position, p1 is the forward vector. The length of p1 should be determined rather by the distance between p0 and p4 than by the speed of your object (as high speeds with close points might result in weird paths). The length of p3 is the same as p1.
    P3 direction could be the forward vector of your vehicle with a given length and a Vector between p0 and p4 (Vector t). Take the angle between the two (Angle A), and make p3 a vector of length p1 with direction of t - angle A.

    Bezier.JPG
    This worked fine for me when teaching my cars to go between points on streets.

    Things to consider with bezier curves:
    They aren't especially fast so performance might get an issue with a lot of objects using them.
    Bezier Curves work with time or percents (0 - 1). Be aware that the distance you get when increasing t by 0.1 changes during the run of the curve.
     
  3. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    I gotta disagree with that one, it's a broad statement and depends on how you implement it.
    The method I use, I tested something like 100 million calls and it only took 2.1 seconds. That's imperceptibly small for even a scene full of objects, you get more overhead just from the objects themselves.

    I also don't think the angles you mention are going to be the same, given that the start and end velocities are going to be different based on user input.


    What happened to p2?
     
  4. spec7or

    spec7or

    Joined:
    Jan 11, 2014
    Posts:
    4
    Thank you both for the replies and great graphs based on my rather vague explanation. So I have implemented a system where p1 is the initial velocity as suggested. P2 is created by making a normalized direction vector from the button up position and p3 and then reversing it across the forward vector. However I still seem to be getting some odd curves where the final point doesn't go where the user clicked. Attached below is the code I am currently using to create a representation of the pathing model. Any suggestions are welcome.


    Thank you for your time.

    Code (CSharp):
    1. if (Input.GetButtonDown ("Fire1")) {
    2.                         Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    3.                         RaycastHit hit;
    4.                         if (Physics.Raycast (ray, out hit, 100)) {
    5.                                 if (FirstClick == true) {
    6.                                         p1.x = hit.point.x;
    7.                                         p1.y = hit.point.z;
    8.                                 }
    9.                                 if (FirstClick == false) {
    10.                                         p4.x = hit.point.x;
    11.                                         p4.y = hit.point.z;
    12.                                 }
    13.                        
    14.                         }
    15.                 }
    16.                
    17.                 if (Input.GetButtonUp ("Fire1")) {
    18.                         Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    19.                         RaycastHit hit;
    20.                         if (Physics.Raycast (ray, out hit, 100)) {
    21.                                 if (FirstClick == true) {
    22.                                         Vector2 Direction = new Vector2 (hit.point.x, hit.point.z);
    23.                                         float throttle = Mathf.Min (Direction.magnitude / 2, 1);
    24.                                         Direction.Normalize ();
    25.                    
    26.                                         p2.x = p1.x + (Direction.x * throttle * speed);
    27.                                         p2.y = p1.y + (Direction.y * throttle * speed);
    28.                                 }
    29.                                 if (FirstClick == false) {
    30.                                         Vector2 Direction = new Vector2 (hit.point.x, hit.point.z);
    31.                                         float throttle = Mathf.Min (Direction.magnitude / 2, 1);
    32.                                         Direction.Normalize ();
    33.                                        
    34.                                         p3.x = p4.x + (-Direction.x * throttle * speed);
    35.                                         p3.y = p4.y + (-Direction.y * throttle * speed);
    36.                                 }
    37.                                 FirstClick = !FirstClick;
    38.                        
    39.                         }
    40.                 }
    41.    
    42.    
    43.                 for (float i = 0; i <= 9; i ++) {
    44.                         Vector2 temp = CalculateCubicCurve ((i + 1) / 10f);
    45.                         ln.SetPosition ((int)i, new Vector3 (temp.x, 0f, temp.y));
    46.                         points [(int)i].transform.position = new Vector3 (temp.x, 0f, temp.y);
    47.                 }