Search Unity

How do you make a game object move in a parabolic trajectory using a quadratic equation?

Discussion in 'Scripting' started by boylesg, Jun 3, 2016.

  1. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Folks I get quadratic equations as it is taught to you in Form 4 (or what ever) with traditional graph paper with positive y up, negative y down, positive x right and negative x left.

    But I am buggered if I can figure out how to make it work simply with Unity's ar$e about coordinate system (compared to graph paper) and a starting X and an ending X that could be any where in world space (any combination of negative and positive).

    I don't want to use the apply force thing to get physics unity's engine to do it for me.

    My current code is thus.

    And this is what I want to do with my game object.


    There simply must be an easy way to calculate Y given an X increment by 0.01f from m_vectStartPos.x.

    But Y is always coming out below the m_vectStartPos.y on screen.

    Has anyone at all had success with this sort of calculation in Unity scripts?

    I just can't seem to get my head around why my code is not working

    I did manage to get my parabolic graph plotted the right way up, as in the above picture, but I can't get the f'ing thing at the right height.

    Code (CSharp):
    1.     private float QuadraticY(float fX)
    2.     {
    3.         float fY = 0.0f;
    4.  
    5.         if (gameObject.name == "RecentBall2")
    6.             fY = (-10.0f * fX * fX);
    7.         else
    8.             fY = (-10.0f * fX * fX);
    9.      
    10.         return fY;
    11.     }
    12.  
    13.     private float GetY(ref float fX)
    14.     {
    15.         float fY = 0.0f;
    16.  
    17.         if ((fX + m_vectStartPos.x) >= m_vectEndPos.x)
    18.         {
    19.             fY = -1000.0f;
    20.         }
    21.         else
    22.         {
    23.             fY = QuadraticY(fX) + m_vectStartPos.y;
    24.             fX += 0.01f;
    25.         }
    26.         return fY;
    27.     }
    28.  
    29.     private void EndMove()
    30.     {
    31.         m_bMove = false;
    32.         DoShow(false);
    33.         transform.localPosition = m_vectOrigPos;
    34.  
    35.         Texture2D textureCurrent = (Texture2D)m_materialRecentBall.GetTexture("_MainTex");
    36.         m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BALL, textureCurrent, gameObject.name);
    37.     }
    38.  
    39.     protected override void Update()
    40.     {
    41.         if (m_bMove)
    42.         {              
    43.             m_fY = GetY(ref m_fX);
    44.             if (m_fY <= -1000.0f)
    45.                 EndMove();
    46.             else
    47.             {
    48.                 m_vectMoveTo.x = m_fX;
    49.                 m_vectMoveTo.y = m_fY;
    50.                 m_vectMoveTo.z = m_vectStartPos.z;
    51.                 transform.localPosition = m_vectMoveTo;
    52.             }
    53.         }
    54.     }
    55.  
     
    Last edited: Jun 3, 2016
  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    One question, why is there so many private methods? It's not like it will change that much if you just simply leave it out
    unity's coordinate system is like any other coordinate system:
    y: up, -y: down, x: east, -x: west, z: north, -z south
    What do you mean it's not the same as a normal coordinate system?
    Instead of 0.0f, 10.0 f, etc, you can simply use an int, like 10, and it will be counted as a float
    that seems pointless
     
  3. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Simply for the purpose of separating out the different bits of the task rather than having one continuous hard to read block of code.

    If I can get it working correctly then I will simplify it.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,536
    I don't care that you have private methods... what I find chilling is that you have a function 'GetY' that passes in a ref pointer to 'm_fX' so that really 'GetY' is actually a 'GetXY' where the return is Y, and the ref is X...

    talk about a confusing interface...


    THere's even more "wtf's" through out this:

    Code (csharp):
    1.  
    2.     private float QuadraticY(float fX)
    3.     {
    4.         float fY = 0.0f;
    5.  
    6. //why? 1) name comparison like this creates a lot of garbage
    7. //also the SAME thing happens either way, what's the point?
    8.         if (gameObject.name == "RecentBall2")
    9.             fY = (-10.0f * fX * fX);
    10.         else
    11.             fY = (-10.0f * fX * fX);
    12.    
    13.         return fY;
    14.     }
    15.  
    Code (csharp):
    1.  
    2.     private float GetY(ref float fX)
    3.     {
    4.         float fY = 0.0f;
    5.  
    6.         if ((fX + m_vectStartPos.x) >= m_vectEndPos.x)
    7.         {
    8. //what, why? from what I'm getting you're saying when the position is past the end x pos, set y for -1000?
    9. //why -1000?
    10.             fY = -1000.0f;
    11.         }
    12.         else
    13.         {
    14. //ok, I kind of get this, you're saying base the height off of how far along the x is...
    15. //but then wouldn't the height be then be dependent on how far we move in the x?
    16.             fY = QuadraticY(fX) + m_vectStartPos.y;
    17. //so we move at a fixed 0.01 units per frame? No control over speed?
    18. //you do know that unity does not have a fixed framerate, this means that your motion is going to be different depending on framerate
    19.             fX += 0.01f;
    20.         }
    21.         return fY;
    22.     }
    23.  
    I honestly don't even know where to start with all this...



    I'd say start over.

    Think about your quadratic arc as a vector function of time.

    f(t) = <tA, tB, tC>

    I'm busy right now, I'll probably back around later to give further assistance.
     
    ArachnidAnimal likes this.
  5. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Yeah well the coordinate system is Unity is bloody confusing with this sort of thing.

    And then bring in blender .fbx's, with their swapped y and z axes and I am even more friggin confused.

    Don't have this sort of problem with windows MFC applications because 0,0 is at the top left of the view port and all x,y values are positive.

    The code below seems to work better - just need to get the bx term (as in ax2 + bx + c) right

    + m_vectStartPos.y (as the c in ax2 + bx + c) seems to put the parabola in roughly the correct y axis position.

    But I need to widen the parabola with the bx term to get the object to land in the right position.

    I removed the ref parameter, tidied up the Quadratic function and deleted the EndMove(...) function from the code snippet below (it is not relevant to the problem)

    Code (CSharp):
    1.     private float QuadraticY(float fX)
    2.     {
    3.         float fY = 0.0f;
    4.  
    5.         if (gameObject.name == "RecentBall2")
    6.             fY = (-0.7f * fX * fX);
    7.         else
    8.             fY = (-2.0f * fX * fX) + (1.5f * fX) + m_vectStartPos.y;
    9.  
    10.         return fY;
    11.     }
    12.  
    13.     private float GetY(float fX)
    14.     {
    15.         float fY = 0.0f;
    16.  
    17.         if (fX >= m_vectEndPos.x)
    18.         {
    19.             fY = -1000.0f;
    20.         }
    21.         else
    22.         {
    23.             fY = QuadraticY(fX);
    24.             fX += 0.01f;
    25.         }
    26.         return fY + m_vectStartPos.y;
    27.     }
    28.  
    29.     protected override void Update()
    30.     {
    31.         if (m_bMove)
    32.         {            
    33.             m_fY = GetY(m_fX);
    34.             if (m_fY <= -1000.0f)
    35.                 EndMove();
    36.             else
    37.             {
    38.                 m_vectMoveTo.x = m_fX;
    39.                 m_vectMoveTo.y = m_fY;
    40.                 m_vectMoveTo.z = m_vectStartPos.z;
    41.                 transform.localPosition = m_vectMoveTo;
    42.                 m_fX += 0.01f;
    43.             }
    44.         }
    45.  
     
    Last edited: Jun 3, 2016
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,536
    if you removed the 'ref' from 'GetY', how is m_fX getting updated?

    [edit]
    scratch that, I see how



    How about you show me the entire class this is from... not knowing the rest of your fields/vars (like m_vectStartPos) and how this all gets a running is rather confusing.
     
  7. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    Could you explain me, why unity coordinate system is bloody confusing?
    Wait until you use a 2D programmers coordinate system (+y is downwards)
    the you have to use the normal 3d system
    then you have to switch to blenders rotated ones (which are rotated, because if you want to create a 2d model, or view something in 2d, you could look at it from the top, and you wouldn't need to use x and z instead of x and y, and BTW, it imports correctly into unity)
     
  8. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,832
    I'm not really understanding the code.
    You should be trying to find two separate things: x = fx(t) and y = fy(t), where t is the amount of time which has elapsed since starting moving the object.
    But in you're code you have y = f(x), which is not making sense to me.
    The y-value should be a function of time, not x distance.

    In your formula you're considering m_fX to be both a distance and time, which is what I think is causing you problems.
     
    Last edited: Jun 3, 2016
    lordofduct likes this.
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,536
    ... [edit] sorry, misinterpreted post of someone else confusing as OP...
     
  10. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    I'm not sure exactly what you're trying to do with the parabola (as TTTTTa said, it seems like x is being used as both distance and time) but if you're just trying to get something to move with an arc-like motion, you can move it by a vector pointing up and right which you then modify by some fake gravity constant, like this:

    Code (csharp):
    1. public Vector3 initialVelocity;  //in the inspector put whatever you want, like (100,100,0)
    2. private Vector3 currentVelocity;
    3. private const Vector3 gravity = Vector3.down * 10f;
    4.  
    5. public void Start()
    6. {
    7.     currentVelocity = initialVelocity;
    8. }
    9.  
    10. public void Update()
    11. {
    12.     transform.Translate(currentVelocity * Time.deltaTime);
    13.     currentVelocity += (gravity * Time.deltaTime);
    14. }
     
    Last edited: Jun 4, 2016
  11. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I echo the "I have no idea what's going on in the OP code" sentiment.

    So let's examine the problem as I understand it. This is pretty much high school maths and physics.

    Motion in 3D space can be studied by breaking the motion into its various component dimensions. X and Y are independent of each other. X position is solely dependent on the initial velocity and time. Y movement is dependent on initial velocity, time, and the acceleration of gravity. Fortunately we can use vector maths to do this all in one equation.

    There are two basic approaches to movement. The first is the iterative approach. This is commonly used in game engines as it is easy to deal with user input. The big drawback of this approach is that it makes predictions a little difficult. Something like this would work.

    Code (CSharp):
    1. Vector3 gravity = new Vector3 (0, 9.8f, 0);
    2. Vector3 velocity = new Vector3 (5, 15, 7);
    3.  
    4. void FixedUpdate () {
    5.     // Update velocity via Newtons law
    6.     velocity += gravity * Time.deltaTime;
    7.    
    8.      // Update position
    9.      transform.position += velocity * Time.deltaTime;
    10. }
    If you need predictions of the objects position at arbitrary future points in time then a deterministic solution might be better. The big drawback here is that collisions and dynamic input gets challanging.

    Code (CSharp):
    1. Vector3 gravity = new Vector3 (0, 9.8f, 0);
    2. Vector3 initialVelocity = new Vector3 (5, 15, 7);
    3.  
    4. Vector3 GetPosition (float time) {
    5.     // Kinematic equations
    6.     return initialVelocity * time + 0.5f * gravity * time * time;
    7. }
    Note that these solutions will converge as the fixed time step gets smaller. But if the fixed time step is too large you will get noticeable differences.
     
    ArachnidAnimal likes this.
  12. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Mainly, because I am used to the windows coordinate system where I don't have to worry about negative coordinate values.

    The possibilities for two coordinates x1,y1 and x2,y2 are -4,0 and -2,0 or -2,0 and 2,0 or 2,0 and 4,0 etc. And I find this complicates such things like finding mid points between them calculating those coordinates relative to the midpoint.

    With the Windows coordinate system, where all values are positive, this complication does not exist.

    With my script above, I think my problem was that my sphere was originally a standard Unity sphere and I just could not get the upside down quadratic curve to start at my game object - it always started below it. But then I swapped it for a sphere created with blender that allows a texture to wrap around it without distortion. And the fact that blender x and z are swapped seems to have some how alleviated the problem I was having - I don't get it but I will take it.
     
  13. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Here is the entire code and the editor windows in unity

    Unity.png

    The idea is that a bingo ball rolls down the slope, hits the ball on the first hexagon and causes it to bounce up to the middle hexagon.....and so on. And all I am doing is passing the numbered ball textures along the chain.

    I am open to suggestions for simplifying it.

    m_vectStartPos contains the localPosition of the sphere on top of the shortest hexagon and m_vectEndPos contains the position of the sphere on top of the middle hexagon.

    OR

    m_vectStartPos contains the localPosition of the sphere on top of the middle hexagon and m_vectEndPos contains the position of the sphere on top of the tallest hexagon.

    m_vectOrigPos contains the localPosition of one of those spheres hanging in mid air.

    The script is re-useable in both cases - I saw no sense in writing two scripts with all but identical code.

    All that is important in the parabola coding is that you have a start point and an end point.




    The script below is attached to those two spheres hanging in mid air so to speak - I put them over there because I was trying OnTriggerEnter etc and I was having problems unless I moved them away from the spheres on top of the hexagons. I am no longer using OnTriggerEnter etc but I have left it as is.

    So when the roller ball hits the sphere sitting on the first hexagon its script (not included in this post) does the following:
    1) Hides the itself.
    2) Changes its numbered texture to the new one from the roller ball.
    3) Sends its previous numbered texture to the first 'jump' ball hanging in mid air.

    Now the script attached to the jump ball is triggered and it does the following:
    1) Moves itself to the same position as the ball on the first hexagon (m_vectStartPos).
    2) Moves itself in a parabola up to the top of the second hexagon until its X values is >= m_vectEndPos.x.
    3) Hides itself and moves itself back into the mid air position (m_vectOrigPos)
    4) Sends it numbered texture to the ball sitting on top of the second hexagon.

    Now the script attached to the ball sitting on top of the second hexagon is triggered and it:
    1) Changes its numbered texture to the one sent by the jump ball.
    2) Shows itself.


    Code (CSharp):
    1. public class RecentBallJumpManager : McCormickMonoBehaviourBase
    2. {
    3.     private bool m_bMove = false;
    4.     private float m_fX = 0.0f, m_fY = 0.0f;
    5.     private Vector3 m_vectOrigPos, m_vectStartPos, m_vectEndPos, m_vectMoveTo;
    6.     private Material m_materialRecentBall = null;
    7.     private GameObject m_gameobjRecentBall = null;
    8.  
    9.     private void GetDetails(string strGameObjectName)
    10.     {
    11.         GameObject gameobj1 = null, gameobj2 = null;
    12.  
    13.         if (gameObject.name == "RecentBall1Jump")
    14.         {
    15.             gameobj1 = FindGO("RecentBall1");
    16.             gameobj2 = FindGO("RecentBall2");
    17.         }
    18.         else if (gameObject.name == "RecentBall2Jump")
    19.         {
    20.             gameobj1 = FindGO("RecentBall2");
    21.             gameobj2 = FindGO("RecentBall3");
    22.         }
    23.         m_gameobjRecentBall = gameobj1;
    24.  
    25.         if ((gameobj1 != null) && (gameobj2 != null))
    26.         {
    27.             m_vectStartPos = gameobj1.transform.localPosition;
    28.             m_vectEndPos = gameobj2.transform.localPosition;
    29.             m_vectOrigPos = transform.localPosition;
    30.         }
    31.     }
    32.  
    33.     // Use this for initialization
    34.     protected override void Start()
    35.     {
    36.         base.Start();
    37.  
    38.         m_materialRecentBall = GetComponent<Renderer>().material;
    39.         GetDetails(gameObject.name);
    40.         DoShow(false);
    41.     }
    42.  
    43.     private GameObject GetRecentBall(string strRecentBallName)
    44.     {
    45.         GameObject gameobj = null;
    46.  
    47.         if (strRecentBallName == "RecentBall1Jump")
    48.             gameobj = FindGO("RecentBall2");
    49.         else if (strRecentBallName == "RecentBall2Jump")
    50.             gameobj = FindGO("RecentBall3");
    51.  
    52.         return gameobj;
    53.     }
    54.  
    55.     protected override void DoReceiveMessage(Parameters p)
    56.     {
    57.         if (p.m_nMsgID == BingoMessageIDEnum.MSGID_SET_BALL)
    58.         {
    59.             Texture2D textureCurrent = (Texture2D)m_materialRecentBall.GetTexture("_MainTex"),
    60.                         textureNew = (Texture2D)p.m_objParam1;
    61.  
    62.             if (textureNew != null)
    63.             {
    64.                 m_materialRecentBall.SetTexture("_MainTex", textureNew);
    65.                 DoShow(true);
    66.                 m_bMove = true;
    67.                 transform.localPosition = m_vectStartPos;
    68.                 m_fX = m_vectStartPos.x;
    69.             }
    70.             if (textureCurrent != null)
    71.             {
    72.                 m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BALL, textureCurrent, gameObject.name);
    73.  
    74.                 GameObject gameobj = GetRecentBall(gameObject.name);
    75.                 if (gameobj != null)
    76.                     SendMessage(gameobj, m_parameters1);
    77.             }
    78.         }
    79.         base.DoReceiveMessage(p);
    80.     }
    81.  
    82.     private float QuadraticY(float fX)
    83.     {
    84.         float fY = 0.0f;
    85.  
    86.         if (gameObject.name == "RecentBall2")
    87.             fY = (-0.7f * fX * fX);
    88.         else
    89.             fY = (-2.0f * fX * fX) + (1.5f * fX) + m_vectStartPos.y;
    90.  
    91.         return fY;
    92.     }
    93.  
    94.     private float GetY(float fX)
    95.     {
    96.         float fY = 0.0f;
    97.  
    98.         if (fX >= m_vectEndPos.x)
    99.         {
    100.             fY = -1000.0f;
    101.         }
    102.         else
    103.         {
    104.             fY = QuadraticY(fX);
    105.             fX += 0.01f;
    106.         }
    107.         return fY + m_vectStartPos.y;
    108.     }
    109.  
    110.     private void EndMove()
    111.     {
    112.         m_bMove = false;
    113.         DoShow(false);
    114.         transform.localPosition = m_vectOrigPos;
    115.  
    116.         Texture2D textureCurrent = (Texture2D)m_materialRecentBall.GetTexture("_MainTex");
    117.         m_parameters1.New(BingoMessageIDEnum.MSGID_SET_BALL, textureCurrent, gameObject.name);
    118.         SendMessage(GetRecentBall(gameObject.name), m_parameters1);
    119.     }
    120.  
    121.     protected override void Update()
    122.     {
    123.         if (m_bMove)
    124.         {            
    125.             m_fY = GetY(m_fX);
    126.             if (m_fY <= -1000.0f)
    127.                 EndMove();
    128.             else
    129.             {
    130.                 m_vectMoveTo.x = m_fX;
    131.                 m_vectMoveTo.y = m_fY;
    132.                 m_vectMoveTo.z = m_vectStartPos.z;
    133.                 transform.localPosition = m_vectMoveTo;
    134.                 m_fX += 0.01f;
    135.             }
    136.         }
    137.     }
    138. }
    139.  
     
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Pure animation? If you don't need your balls to do physics in any way, why not use an animation curve?
     
  15. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    If an animation curve involves X images times 75 balls then we don't want to use it.

    Originally the whole app involved sprites only and we were going to implement the roller ball bit as 20 or so individual sprite images, each in a different stage of the roll.

    But that meant 25 (or so) x 75 = 1875 individual sprite images for each rolling ball.....which is a little excessive.
     
  16. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I am still some what unclear about the difference between localPosition and position and which one should use to move objects.
     
  17. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    How about you go look up what an animation curve is. I'm not here to hold your hand and disabuse you of all of your preconceived notions.

    They are pretty much what they say. position is the objects position in world space. localPosition is its position relative to the parent GameObject.

    The one to use depends on what you are trying to do. Do you want motion relative to world space (eg a projectile moving through space) or relative to the parent GameObject (eg my arm moving relative to my torso)?
     
    gorbit99 likes this.
  18. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    What do you think, unity users use, when they need to move a gun for example? They wont animate it to every single x and z value, they will use an animation curve, which works in (let's just say) local position, so the animation has a starting point, and an end point, and if you play this animation at -100.467 x and +10000.45 y, then it will still work, and the same animation will play, but it will be offset

    And what do you mean by windows coordinate system? If you mean that not having to deal with negative values, because if you run off the screen it won't show, then you're wrong, because in reality, a coordinate system has -x and -y values, and real life has negative values, and for example -x^2 is staright up a thing that goes into negative infinity
     
  19. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Well unless you are dealing with an element that is bigger than the window then you ignore negative values.
    And dealing with elements bigger than the window is fairly uncommon for Windows programs outside of document editing.
    Most of the time you (or at least I) are dealing with a window containing various controls (tabs, edit field and such like) or a window containing simple formatted or unformatted text.
    And for control based applications you have the resource editor to arrange all your controls and where negative window coordinate values are just not relevant.
     
  20. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Thanks for the tip anyway and I will check these out and see if I can use it in my particular situation. Anything that takes the headache out of doing what, at first sight, appears to be a very trivial task is fine by me.

    These animation curves look as though they are part of the animation (.anim) that you have in conjunction with an animator controller. I have tried these with sprite images of course.

    Is it possible to instead use 3D objects in them rather than sprites
     
    Last edited: Jun 4, 2016
  21. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    Not really, i always worked with negative values, since they are an essential part of game programming, and I never saw a problem with them, you calculate the distance between them the same way, the midpoint in a same way, the only difference in my opinion is, that you can't sqrt them.
     
  22. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    My parabola generating quadratic function would probably produce the desired results in unity if you could flip the y axis so that rising up the screen results in increasingly negative y values.

    As it is there seems to be a fundamental conflict between -aX2 + bX + c that is required generate a parabola the right way up and unity's y axis that increase in y value as you go up the screen.

    There is probably some mathematical technique to get around this conflict but I am afraid my knowledge of maths is not sufficiently advanced to know how to do it.
     
  23. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    There is this amazing operator that can be used to flip a negative number to a positive one. When applied to a parabola it will turn it upside down.

    -
     
    gorbit99 likes this.
  24. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    lel
    Xna is a really popular way of creating games for windows (and for other stuff with monogame) and it has an y coordinate, which grows in negative direction, and look:
    http://lmgtfy.com/?q=xna+coordinate+system+is+weird
    A normal coordinate systems y value grows upwards
     
  25. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I tried that and it also flips the parabola unfortunately!
     
  26. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    That's what you wanted, isn't it, if your parabola is in the right direction, why would you want to flip it?
     
  27. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Naturally, and it seems entirely straight forward.

    But, for what ever reason, I simply cannot get a quadratic equation to work with Unity. If the curve is the right shape it starts below where I want it to. I don't get and I think I have wasted enough time with it.

    Time to try something new - perhaps this animation curve thing will make the task a lot easier.
     
  28. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    No, you misunderstand.
    It also flips the curve such that it has the appearance of y = x2.

    Like I said I just DON'T GET why this is not a QED problem in Unity.
     
  29. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    here
    Try it yourself.
    Stick in a sphere and then another above and to the right of it. And then see if you can write a script that does the y value calculation in the form of ax2 + bx +c such that you move the first sphere along an upside down parabola and land it on top of the second sphere.

    If you succeed then I am going to do a Homer Simpson, slap my forehead and wonder why I could not do it!
     
  30. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    That is probably half my problem - I have spent no time writing games until I started mucking with Unity. So I simply do not have enough practice yet with these sorts of mathematical problems that are part and parcel of game programming.
     
  31. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    (Can I? I mean, is it allowed, nevermind, i will do it)

    It's only you, who has a problem with this, we suggested a lot of ways to solve this, and you're just not listening to them
     
  32. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Calm down buddy!
    I have decided to give this AnimationCurve thing a try.
    So how is that not listening to your collective suggestions exactly????
    After finding a piece of example code these things look as though they will achieve my bouncing effect with no mathematical headaches.
    And believe me I am all for doing things the easy way if I am aware of that easy way.
     
  33. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    I'm calm, I'm just surprised, that you got surprised, because of the flipping of the curve (surpriseception)
    What does "I gave it a try" mean? Did you solve the problem? If yes, why are you still posting here instead of closing the thread, if no, why didn't you tell us, what you couldn't do?
     
  34. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Aft
    I have given this quadratic equation thing a damn good go and I have still not managed to make it work reliably in all situations. Basically I can't be f'ed with it any more - I'm over it!

    So I am switching to this animation curve method. So far I have got my ball to move horizontally with it but yet to figure out how to make it move vertically when you call m_vectNewPos.y=m_AnimationCurve.Evaluate(m_fTimer); with m_fTimer+=fDeltaTime; with each iteration of Update().
     
  35. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Apparently I'm really bored tonight. I drew up a really rough solution to your problem. It has two spheres. And it draws a parabola between them using a particle system. You don't need the particle system, once you have the curve you can follow it in whatever fashion you like. But it makes a nice visual representation. And it demonstrates how you can easily move the endpoints about and still have the curve function properly.

    Two points is not enough to fully define a parabola, a parabola actually has three degrees of freedom. I left an eccentricity value that you can manipulate to control the curvature.

    I also didn't bother to generalize it for 3D. But its the same solution.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Curve : MonoBehaviour {
    5.  
    6.     ParticleSystem system;
    7.     ParticleSystem.Particle[] particles = new ParticleSystem.Particle[100];
    8.     [SerializeField]
    9.     Transform start;
    10.     [SerializeField]
    11.     Transform end;
    12.     [SerializeField]
    13.     float entricity;
    14.  
    15.     // Use this for initialization
    16.     void Start () {
    17.         system = GetComponent<ParticleSystem>();
    18.  
    19.         for (int i = 0; i < particles.Length; i++)
    20.         {
    21.             particles[i].startLifetime = Mathf.Infinity;
    22.             particles[i].lifetime = Mathf.Infinity;
    23.             particles[i].startColor = Color.red;
    24.             particles[i].startSize = .1f;
    25.         }
    26.         system.SetParticles(particles, 100);
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update () {
    31.  
    32.         Vector3 targetPosition = end.position - start.position;
    33.         for (int i = 0; i < particles.Length; i++)
    34.         {
    35.             float xValue = targetPosition.x / particles.Length * i;
    36.             float a = entricity;
    37.             float b = (targetPosition.y - a*targetPosition.x*targetPosition.x) / targetPosition.x;
    38.             float yValue = a * xValue * xValue + b * xValue;
    39.             particles[i].position = new Vector3(xValue, yValue) + start.position;
    40.         }
    41.         system.SetParticles(particles,100);
    42.     }
    43. }
     

    Attached Files:

    h00man and gorbit99 like this.
  36. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    A particle system??????

    Thanks for that BoredMormon - I am very intrigued how you used a particle system to solve the problem.

    But I kind of like the idea of this AnimationCurve thing if I can figure out how to use it properly.
    So far the evaluate function is just returning 1 for y all the time. Does that mean anything to you?
     
  37. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    That you didn't animate it properly?
     
  38. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    The package is there, feel free to download it and have a look.

    Worth noting that I didn't solve it with a particle system. I just used a particle system to display the solution. It's a quick and dirty prototype hack. If I was doing it for production code the parabola generation and the display would be split up into two classes. One class to produce the parabola and another that would actually consume it.

    The guts of the solution goes something like this.
    1. Grab the start and end positions
    2. Subtract the start position from the end position. This sets the value of c to zero.
    3. Set an arbitrary value for a
    4. Set b = (y1 - ax1^2)/x1
    5. Calculate the value of y across the parabola with y = ax^2 + bx
    6. Add the start position onto each position from step five
    You can do it without shifting frames of reference. But it makes the math more complex, so why bother?
     
  39. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Ah, so the only practical way it can be done (short of being a PHD in maths) is with the coordinates.
    OK I'll give it another try.
    Never let it be said that I am not f'ing determined mother @ucker regardless of my level of knowledge.
    I still have the irritating problem that I actually have to modify the z axis of my game object rather than the y axis due to it being blender generated!
     
  40. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    That is not Phd level math, they teach you about quadratics, trig and vectors in high school math, and it should have been gone over again in the CS classes you talked about in previous posts.
     
  41. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Your solution has the problem I had in that the parabola is the wrong way up. I changed your a to -a and the curve looks like this starting at the lower most sphere:



    This is what we want:


    You need to know the centre x of the curve and, while deltaX is less that that you add f(deltaX) to your transform.localPosition.y and when it is greater than the mid point you subtract f(deltaX) from your transform.localPosition.y

    Like I said applying seemingly simple quadratic equation to Unity's coordinate system is not as straight forward as you might assume.
     
    Last edited: Jun 4, 2016
  42. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    The concept is form4 stuff but applying it to computer graphics coordinate systems does not appear to be as straight forward as one might assume.

    I was exaggerating about the PHD by the way.
     
  43. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I've only used early high school maths in my solution. With first year uni calculus and algebra you pretty much have enough math to write your own game engine. None of this is especially difficult.

    There are a dozen different ways this can be done in practice. Each has its own perks and disadvantages. Your problem definition seems to be very slippery. It might be valuable to drop back to software engineering 101. What inputs do I have? What outputs do I want? Once this is properly defined its pretty straight forward for an experienced unity dev to get you on the right path. But at the moment I feel like the goal posts are changing each time you post.

    Make it a child of an empty GameObject, rotated appropriately. Or just tell blender to export it with a different coordinate basis.

    We've noticed. Indeed that may be part of your problem. You seem dead set on forcing Unity to work in the way you are used to other software working. Try relaxing and doing things the way that Unity is built.
     
  44. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I assume this is a reference to my solution?

    You can get any sort of behavior you want by manipulating the eccentricity on the Curve game object. As I pointed out in my post, a parabola has three degrees of freedom. That means there are an infinite number of parabolas that pass through any two given points.

    If you wanted to restrict it probably come up with a third constraint from gravity and Newton's laws. Or you could define a third point on the parabola, which would define it exactly. Or you could just pass in an eccentricity value as I did.

    Here is a picture of the behavior in my package. From top to bottom the eccentricity values are -1, -0.5, 0. 0.5 and 1. Note that all of these curves are parabolas that pass through the centers of both spheres.

    Differing eccentricity values.png
     
    Last edited: Jun 4, 2016
  45. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    OK got ya. What does eccentricity equal then? Is that a unity constant or something?
    First attempt at just making 'a' negative gave me the wrong curve.
    But if I replace eccentricity with '-1' then I get what you got.
    Code (CSharp):
    1.             float xValue = targetPosition.x / particles.Length * i;
    2.  
    So xValue is just the equivalent of Time.deltaTime or 0.01f (that I was previously using)

    Code (CSharp):
    1.  float a = -1.0f;//entricity;
    2.  
    a as in ax2 + bx + c...but where is the value for 'entricity' coming from - it appears to default to 1.0f?

    Code (CSharp):
    1.  
    2.             float b = (targetPosition.y - a*targetPosition.x*targetPosition.x) / targetPosition.x;
    3.            
    I don't get what you are doing here to get a value for b (not as straight forward as plotting these things on graph paper in form 4)

    Code (CSharp):
    1.    float yValue = a * xValue * xValue + b * xValue;
    2.             particles[i].position = new Vector3(xValue, yValue) + start.position;
    3.  
    And I get these - pretty straight forward.
     
    Last edited: Jun 4, 2016
  46. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
  47. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Mmmmmm! I forgot you can do vector arithmetic.....I have been doing it the hard way.....more typing
     
  48. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Eccentricity is set via the inspector. Its a pretty standard Unity approach.

    My model is build deterministicly. Its independent of time. But yes, you could use xValue to represent time.

    a as in ax^2 + bx + c, yes. Entricity (which it looks like I spelled wrong) comes from the inspector.

    This is just a straight forward rearrangement of the formula above. Working as follows:

    if position1 y (0,0) and postion 2 = (y1,x1) and y = ax^2 +bx + c
    then 0 = a(0)^2 + b(0) + c
    c = 0
    and y1 = a(x1)^2 + b(x1) + 0
    y1 - a(x1)^2 = b(x1)
    (y1 - a(x1)^2)/x1 = b

    So now we have an equation relating a and b. Since we don't have a third constraint, any value of a will work. Which is why I set a to a value from the inspector.

    Making sense now?
     
  49. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    So it does sound like you're just moving a thing in an arc, in which case there's really no need to use parabolic equations. Did you read mine or BoredMormon's post about using velocity? If it helps, you can think of the equation for distance (d = v0t + .5gt^2) as being a rearrangement of ax^2 + bx where a is .5g, b is v0 (initial velocity) and x is t.

    I'd try to start thinking of everything in terms of vectors if you really want to get anywhere with games, especially 3D. Move things by using a velocity vector * time. Mimic acceleration or gravity by changing the velocity over time.
     
  50. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    YES! Thankyou mormon. I get it.
    You assume 0,0,0 because we did that the vector arithmetic to get pos2 relative to pos1.