Search Unity

Projection/Trajectory Arc?

Discussion in 'Scripting' started by mehware, Aug 9, 2008.

  1. mehware

    mehware

    Joined:
    Nov 19, 2007
    Posts:
    739
    You know how in golf games you can set an arc and move it around with the mouse. How would I go about doing that.

    I think I will use the line/tube renderer, but I am confused how to convert the 2D mouse space into a moving arc.

    When you move the cursor down to the bottom of the screen the arc would get closer and higher. when you move it up it would get further and lower.

    Changing the force (or club if it was a golf game) would change the initial position (how far the arc is is from the player).

    when the mouse is at the middle of the screen its got a 45 degree trajectory.

    Any input would be great.
     
  2. UVRadiation

    UVRadiation

    Joined:
    Jul 21, 2008
    Posts:
    183
    You can use a very simple quadratic Bezier formula (I got it from wikipedia)
    and it works pretty good for me for controlling arcs ( I use it to draw the arms of a monkey...)

    Code (csharp):
    1.  
    2. function GetQuadraticCoordinates(t : float) : Vector3 {
    3.     return Mathf.Pow(1-t,2)*p0 + 2*t*(1-t)*c0 + Mathf.Pow(t,2)*p1 ;
    4. }
    where:
    p0 - is the start point
    p1 - is the end point
    c0 - is the middle point ( controlling the arcness )
    t - between 0 and 1

    just convert the v input (with some scale ) to the y of c0 to control the height of the arc.
    and do something like :
    Code (csharp):
    1.  
    2. function Start(){    GetComponent(LineRenderer).SetVertexCount(sections);
    3. }
    4.  
    5. function Plot() {
    6.     var t : float ;    
    7.     for (var i : int = 0 ; i < sections ; i++ ){
    8.         t = i/(sections-1) ;
    9.         lineRenderer.SetPosition (i ,GetQuadraticCoordinates(t));
    10.     }
    11. }
     
    macka1080 likes this.
  3. mehware

    mehware

    Joined:
    Nov 19, 2007
    Posts:
    739
    I do,

    Code (csharp):
    1.  
    2. function GetQuadraticCoordinates(t : float) : Vector3
    3. {
    4.     var mousePos = Input.mousePosition;
    5.     middle.x = mousePos.x;
    6.     middle.y = mousePos.y;
    7.     middle.z = end.position.z - start.position.z;
    8.     return Mathf.Pow(1-t,2)*start.position + 2*t*(1-t)*middle + Mathf.Pow(t,2)*end.position;
    9. }
    10.  
    11. function Plot() {
    12.     var t : float ;    
    13.     for (var i : int = 0 ; i < 10 ; i++ ){
    14.        t = i/(10-1) ;
    15.        lineRenderer.SetPosition (i ,GetQuadraticCoordinates(t));
    16.     }
    17. }
    18.  
    It kinda draws an arc but nothing happens when I move the mouse up or down.
     
  4. UVRadiation

    UVRadiation

    Joined:
    Jul 21, 2008
    Posts:
    183
    I attached a project that does that
    If you need to convert the mouse position to world coordinates , you can use - Camera.ScreenToWorldPoint
    or Camera.ScreenPointToRay and then find a point on the ray in the distance you want.



    :wink:
     

    Attached Files:

  5. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    Thanks for that script! I'm having trouble figuring out how to move something along that arc, however? Could you give me a hint as to what to do exactly? I tried using
    something like:
    Code (csharp):
    1.  
    2. transform.TransformPoint(0,middle.y,end.z)
    3.  
    but no luck..
     
  6. UVRadiation

    UVRadiation

    Joined:
    Jul 21, 2008
    Posts:
    183
    hi jonyjl,

    Code (csharp):
    1.  
    2.  
    3. transform.position = bezier.GetQuadraticCoordinates(Mathf.Lerp(0.0,1.0,Time.time) , start.position ,  middle.position , end.position );
    4.  

    That will move the transform along the arc in a second, the first value Mathf.Lerp(0.0,1.0,Time.time) is just a number from 0 to 1 that represents how far along the curve you want the coordinate.
    good luck!
     
  7. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    I do try that, however I have:

    Note: "thePlayer" is the player that moves around. It has 3 children which are empty transforms (gameobjects) that are
    declared in the code as: start , middle and end.

    Those determine the angle.

    Code (csharp):
    1.  
    2. var thePlayer: GameObject;
    3. var start: Transform
    4. var middle: Transform
    5. var end: Transform
    6.  
    7. var canThrow = false;
    8. var throwable : GameObject;
    9. var clone: GameObject;
    10.  
    11. function Update()
    12. {
    13.      If(Input.GetButtonDown("q"))
    14.      {
    15.           clone = Instantiate(throwable,thePlayer.position,thePlayer.rotation);
    16.           canThrow =  true;
    17.      }
    18.  
    19.      If(canThrow)
    20.      {
    21.            clone.transform.position  = bezier.GetQuadraticCoordinates(Mathf.Lerp(0.0,1.0,Time.time) , start.position ,  middle.position , end.position );
    22.          
    23.      }
    24.  
    25. }
    26.  
    27.  

    When I push play, and click "q" immediately the throwable starts at "thePlayer" 's position and rotation as expected.

    But say I wait 2 seconds after I push play to click "q": the "throwable" (clone) is instantiated, but it starts further along the arc.

    If I wait too long and click "q" the instantiated object ends up in the end position.

    What I think it happening is as time goes by, the bezier.GetQuadraticCoordinates returns a higher value with the variables passed to it (maybe a Time.time issue)

    I've tried dividing Time.time/20 etc but that just delays the same thing... what's goin on? :p
     
  8. UVRadiation

    UVRadiation

    Joined:
    Jul 21, 2008
    Posts:
    183
    Time.time - is the time of the scene
    in the beginning of the scene it’s 0.0 and after one sec it’s 1.0
    when the value is 1.0 the object is at the end of the arc.
    have some offset time for when “q” was first clicked -

    Code (csharp):
    1. offsetTime = Time.time;
    then when you use the lerp do:

    Code (csharp):
    1. Mathf.Lerp(0.0,1.0,Time.time-offsetTime)
    that way the second is counted from when you first pressed “q” and not form the beginning of the scene.
    to slow down the flight like you said just divide the (Time.time-offsetTime) with some number.
    I would move the fly code to the clone object if you want to have several item to fly at the same time but I don’t know if that’s actually what you need.
     
  9. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    PERFECT! Thanks I actually had that set up but I had too much thought in it.. I had an "endTime" too but the end time IS Time.time - offsetTime :D

    Thanks a lot all of this makes much sense I just couldn't get it out of my brain haha
    :p
     
  10. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    An issue with the line renderer is that the polys always face the camera. So it's going to cause a twist in the ARC at the peak. how do I fix this? I want to add an animated texture on the line renderer to have a nice little aiming system.. Thanks again guys.
     
  11. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I don't think there is any way around this with the line renderer. You may be able to fall back on the Mesh API but the "line" will be rendered in perspective if you use that approach.
     
  12. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
  13. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    looks neat :p

    can you slap a material on them lines? I don't see that as an option?
     
  14. jonyjl

    jonyjl

    Joined:
    Aug 6, 2010
    Posts:
    32
    woops, spoke too soon :p


    "Then make a VectorLine object, giving it a name, the points, a material, the line width in pixels, and an end cap length:"

    var myLine = new VectorLine ("Line", linePoints, lineMaterial, 2, 0);


    lol