Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Launch a golf ball a certain distance 2D

Discussion in 'Getting Started' started by GolfPro1, Jul 30, 2021.

  1. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Hi, I have a golf ball I would like to add a force too to travel a certain distance in 2d.
    If I use
    Code (CSharp):
    1. rb.velocity = 0, 1(or aim direction);
    the ball will continue travelling and not stop.
    How can I get the ball to stop at say a distance of 100 along this direction?
    All help appreciated.
     
  2. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    If you're using the physics system, you shouldn't be setting the velocity directly. I mean, think about it: if you're setting the velocity explicitly, that's what it's going to remain until you change the value to something else. With rigidbodies, you apply force to it using AddForce and let the physics system decide what to do with it from there.

    However, if your goal is to make the ball only move a certain distance that you've already computed, it sounds like you don't actually want to use the physics system at all. You would just move it along the path you want over time, animating it as needed for bouncing or rolling to a stop.
     
  3. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    If I use AddForce the ball continually speeds up along its direction.
    I need to add a force along a direction and let the speed come to a stop similar to a mini golf game.
    Any answers to include the code for making this happen is appreciated.
     
  4. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Are you running AddForce in the Update method? Because yeah, that gets called every frame, so it would be doing exactly that. AddForce is something you want to execute once when a specific action is performed (like hitting the ball).
     
  5. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Yeah the only info I could get was AddForce in fixed update, so you are saying use AddForce in a function to get the desired effect.
    A example of how to do this would help. Do I use AddForce.Impulse etc, Ii could do with the specific command.

    Code (CSharp):
    1. // Update is called once per frame
    2.     void FixedUpdate()
    3.     {
    4.         if (Input.GetKeyDown(KeyCode.H))
    5.         {
    6.             HitBall();        
    7.         }
    8.  
    9.      
    10.     }
    11.  
    12.     private void HitBall()
    13.     {
    14.         myRb.AddForce(aimDirection * force);
    15.     }
    The ball also continues with this code

    Code (CSharp):
    1. private void HitBall()
    2.     {
    3.         myRb.AddForce(aimDirection * force, ForceMode2D.Impulse);
    4.     }
    Code (CSharp):
    1. private void HitBall()
    2.     {
    3.         myRb.AddForce(aimDirection, ForceMode2D.Impulse);
    4.     }
    So far all Im getting is the ball to continue.
     
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    If you add a force (or, for that matter, set the velocity) just once, but the ball never stops, then it means you do not have physics set up correctly for the ball and environment. In particular, check your friction and drag settings. These must be nonzero, or the ball will never have any reason to slow down.
     
  7. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    The ball isnt setup to stop due to the environment.
    I did apply a 2d material but this isnt colliding with the ground but the drag should effect it, but the code at the moment isnt correct.
    The ball should stop due to the force applied in a certain manner and drag.
    Knowing the difference which type of force to apply and give it a set of attributes for direction and force is what I`m trying to find out.
    If anyone wishes to respond could you please give a example in code of which force to apply .e.g. rb.AddForce + rest of the commands/ rb.Velocity etc, which can be adjusted for certain distances.
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    No, that's not it at all. You don't need to apply any forces to get a Rigidbody to stop moving. It will do that all by itself, if you have your friction and drag coefficients set correctly. If you don't, then it will not. There is no code we can show you that will fix your friction and drag coefficients.

    But yeah, the physics engine is confusing and you usually end up fighting it to get the behavior you want. I'll go back and second @Schneider21 's suggestion that maybe you shouldn't be using it at all. For something simple like a 2D golf game, it might be easier to just code the motion yourself. See here for an example.
     
  9. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    The perspective is 2D Top-down not horizontal just to be clear.
    The move towards target would just make the game point and click.
    The ball needs to be launched a certain direction to start off with.
    A friction material to the ground might accomplish the ball to stop but this needs to be addressed after the ball is launched correctly, then height needs to be added also.
    The question is which function is best to accomplish launching the ball, a direction, distance, and again a clear example would help.
     
  10. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Linear Drag was 0. This stops the object you are trying to move.
    Code (CSharp):
    1. myRb.AddForce(aimDirection * force);
    This will fire the gameobject with the force it is applied and stop if you add linear drag.

    The question is now how to add height to the ball given the different angle of the clubface.
    Thanks for your help all and any suggestions for height please add to the question.
     
  11. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I don't understand how height applies if this is a top-down 2D game. Height would require a third dimension, would it not?
     
  12. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    The angle of a pitching wedge is 56 degrees, the angle of a driver is 11 degrees.
    This would make the ball go different heights along its trajectory.
    Currently I have a vector2 aim direction being applied to addforce(see code above).
    Is it possible to use a Vector3 (aimdirection * force, height) in a 2D game?
    I have added a shadow under the ball to give a graphical representation of this to add realism to the game.
     
  13. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    The rigidbody is 2D, therefore only a Vector2 can be applied not a vector3 which means it cannot display height.
    I have added a shadow to the ball (transform.position or child of ball) which along the balls trajectory needs to be adjusted to give the perception of height.

    When you play a golf shot, the ball climbs gradually and reaches its maximum height say at 50% along its trajectory and remains there until 75% and then decreases its height.

    Does anybody have a method to apply this to the shadow to simulate height, thanks.
     
  14. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    I have added a waitforfixedupdate Ienumerator to find the speed of the ball. Here is the code as it stands.

    Code (CSharp):
    1. public class BallVelocity : MonoBehaviour
    2. {
    3.     public Rigidbody2D myRb;
    4.     public Vector2 aimDirection;
    5.     public float force;
    6.     public Vector2 ballPosition;
    7.     public float ballSpeed;
    8.     public bool isPlaying;
    9.  
    10.     public GameObject ballshadow;
    11.     public float ballHeight = 0f;
    12.  
    13.     private void Update()
    14.     {
    15.         if (Input.GetKeyDown(KeyCode.H))
    16.         {
    17.             HitBall();
    18.         }      
    19.     }
    20.  
    21.     IEnumerator CalcSpeed()
    22.     {
    23.         isPlaying = true;
    24.         Debug.Log("isplaying: " + isPlaying);
    25.  
    26.         while (isPlaying)
    27.         {
    28.             ballPosition = transform.position;
    29.             //shadow follows behind ball
    30.             ballshadow.transform.position = new Vector2(myRb.position.x, myRb.position.y - 1f);
    31.            
    32.             yield return new WaitForFixedUpdate();
    33.  
    34.             ballSpeed = Mathf.RoundToInt(Vector2.Distance(transform.position, ballPosition) / Time.fixedDeltaTime);
    35.  
    36.             if (ballSpeed <= 0f)
    37.             {
    38.                 myRb.velocity = Vector2.zero;
    39.                 isPlaying = false;
    40.                 Debug.Log("isplaying: " + isPlaying);
    41.                 //ballshadow.SetActive(false);
    42.                 //shadow moves to ball position
    43.                 ballshadow.transform.position = new Vector2(myRb.position.x, myRb.position.y - 0.25f);              
    44.             }
    45.         }
    46.     }
    47.  
    48.     private void HitBall()
    49.     {
    50.         myRb.AddForce(aimDirection * force, ForceMode2D.Impulse);      
    51.         StartCoroutine(CalcSpeed());
    52.     }
    53. }
    With having the speed of the ball worked out would anybody have a method to simulate height with the shadow along the balls trajectory, thanks.
     
  15. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    I`m now working on the Aiming part of the game and wonder if anyone could help.
    I`m getting a array out of range error although it looks correct if anyone can see the error or a better way to loop through the clubs and improve the aim would be appreciated, thanks.

    Code (CSharp):
    1. public class Player1 : MonoBehaviour
    2. {
    3.  
    4.     private Animator myAnim;
    5.     public GameObject aimCursor;
    6.     public Vector2 aimdistance;
    7.     public string[] myClubs = new string[3];
    8.     public int clubSelected;
    9.  
    10.     public Text clubSelectedText;
    11.     public Vector2 ballPosition;
    12.     public int[] clubDistances = new int[3];
    13.  
    14.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    15.     private void Start()
    16.     {
    17.         //aimdistance = selected club max distance
    18.  
    19.         //INITIALIZE ARRAY
    20.         myClubs[0] = "Driver";
    21.         myClubs[1] = "Pitching Wedge";
    22.         myClubs[2] = "Putter";
    23.  
    24.         clubDistances[0] = 50;
    25.         clubDistances[1] = 32;
    26.         clubDistances[2] = 2;
    27.        
    28.         myClubs[clubSelected] = myClubs[0];
    29.         ballPosition = BallVelocity.instance.ballPosition;
    30.         aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y + clubDistances[0]);    
    31.     }
    32.  
    33.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    34.  
    35.     private void Update()
    36.     {
    37.         if (Input.GetKeyDown(KeyCode.UpArrow))
    38.         {
    39.             //get current club move right from club
    40.             ChangeClubUpMethod();                
    41.         }
    42.  
    43.         if (Input.GetKeyDown(KeyCode.DownArrow))
    44.         {
    45.             //get current club move left from club
    46.             ChangeClubDownMethod();          
    47.         }
    48.  
    49.         if (Input.GetKeyDown(KeyCode.RightArrow))
    50.         {
    51.             //get current club move right from club
    52.             AimRight();
    53.         }
    54.  
    55.         if (Input.GetKeyDown(KeyCode.LeftArrow))
    56.         {
    57.             //get current club move left from club
    58.             AimLeft();
    59.         }
    60.     }
    61.  
    62.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    63.  
    64.     private void Awake()
    65.     {
    66.         myAnim = GetComponent<Animator>();
    67.  
    68.         aimCursor.transform.position = new Vector2(ballPosition.x, ballPosition.y);
    69.     }
    70.  
    71.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    72.  
    73.     void ChangeClubUpMethod()
    74.     {
    75.         //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    76.         //get ball position
    77.         ballPosition = BallVelocity.instance.ballPosition;
    78.  
    79.         for (int i = 0; i < myClubs.Length; i++)
    80.         {        
    81.        
    82.             if (i < myClubs.Length)
    83.             {
    84.                 //change club up
    85.                 clubSelected++;            
    86.             }
    87.             else
    88.             {
    89.                 clubSelected = 0;
    90.             }
    91.  
    92.             aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y + clubDistances[clubSelected]);
    93.             clubSelectedText.text = myClubs[clubSelected];
    94.             i = myClubs.Length;
    95.         }                  
    96.     }
    97.  
    98.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    99.  
    100.     void ChangeClubDownMethod()
    101.     {
    102.         //get ball position
    103.         ballPosition = BallVelocity.instance.ballPosition;
    104.  
    105.         for (int i = myClubs.Length; i > 0; i--)
    106.         {
    107.             if (clubSelected > 0)
    108.             {
    109.                 //change club up
    110.                 clubSelected--;
    111.             }
    112.             else
    113.             {
    114.                 clubSelected = myClubs.Length;
    115.             }
    116.         }
    117.            
    118.         aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y + clubDistances[clubSelected]);
    119.         clubSelectedText.text = myClubs[clubSelected];
    120.         clubSelected = myClubs.Length;
    121.     }
    122.  
    123.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    124.  
    125.     void AimLeft()
    126.     {
    127.         //move aim cursor left 1 unit
    128.         //move left code here
    129.         aimCursor.transform.position = new Vector2(aimCursor.transform.position.x,aimCursor.transform.position.y);
    130.     }
    131.  
    132.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    133.  
    134.     void AimRight()
    135.     {
    136.         //move aim cursor right 1 unit
    137.         //move right code here
    138.         aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y);
    139.     }
    140.  
    141.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    142.  
    143.     public void SwingClubAnimation()
    144.     {
    145.         myAnim.SetBool("playplayer1", true);
    146.     }
    147.  
    148.     public void StopSwingAnimation()
    149.     {
    150.         myAnim.SetBool("playplayer1", false);      
    151.     }
    152. }
     
  16. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It'd be easier to help you if you said which line the error is on.

    But from a quick glance, it looks to me like the loop on lines 105-116 could exit with clubSelected set to myClubs.Length. And then on line 119 you try to use that to index into myClubs. That's out of range (the valid indexes are 0 through myClubs.Length-1).
     
  17. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Thanks Joe, the error was on line 119.
    I added the -1 to the changeclubsup method and no error.
    The change clubsdownmethod now throws up the error if you tell me how to correct this.


    Code (CSharp):
    1. void ChangeClubUpMethod()
    2.     {
    3.         //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    4.         //get ball position
    5.         ballPosition = BallVelocity.instance.ballPosition;
    6.  
    7.         for (int i = 0; i < myClubs.Length; i++)
    8.         {        
    9.             if (clubSelected < myClubs.Length - 1)
    10.             {
    11.                 //change club up
    12.                 clubSelected++;            
    13.             }
    14.             else
    15.             {
    16.                 clubSelected = 0;
    17.             }
    18.  
    19.             aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y + clubDistances[clubSelected]);
    20.             clubSelectedText.text = myClubs[clubSelected];
    21.             i = myClubs.Length;
    22.         }                  
    23.     }
    24.  
    25.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    26.  
    27.     void ChangeClubDownMethod()
    28.     {
    29.         //get ball position
    30.         ballPosition = BallVelocity.instance.ballPosition;
    31.  
    32.         for (int i = myClubs.Length; i > 0; i--)
    33.         {
    34.             if (clubSelected > 0)
    35.             {
    36.                 //change club up
    37.                 clubSelected--;
    38.             }
    39.             else
    40.             {
    41.                 clubSelected = myClubs.Length;
    42.             }
    43.  
    44.             aimCursor.transform.position = new Vector2(aimCursor.transform.position.x, aimCursor.transform.position.y + clubDistances[clubSelected]);
    45.             clubSelectedText.text = myClubs[clubSelected];
    46.             i = 0;
    47.         }
    48.     }
    49.     //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
     
  18. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Got it thanks.

    Code (CSharp):
    1. f (clubSelected > 0)
    2.             {
    3.                 //change club up
    4.                 clubSelected--;
    5.             }
    6.             else
    7.             {
    8.                 clubSelected = myClubs.Length - 1;
    9.             }
    Thats part 1 of my issue resolved. The next is for the input left and right to adjust the aim if anyone knows a good method for this.
    Thankyou.
     
  19. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    If I press left to aim the cursor left this would be incorrect. I need the aim cursor to rotate around the player in a circle to aim correctly. Would anyone know how to do this?
     
  20. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    Code (CSharp):
    1.   if (Input.GetKeyDown(KeyCode.LeftArrow))
    2.         {
    3.             //aim cursor new position aaround player
    4.             aimCursor.transform.position = new Vector2(/*Help here with cursor position*/);
    5.         }
     
  21. GolfPro1

    GolfPro1

    Joined:
    May 21, 2016
    Posts:
    37
    I have a question on Tilemaps.
    I have 5 tiles, fairway, light rough, rough , rough and bunker. I have added a tilemap collider 2d.
    If I use ontriggerstay for when the ball stops on the tile, I need to know what type of tile the ball is on, ie fairway, rough etc.
    Would anyone know how to add this to my tiles, thanks.
     
  22. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please open separate topics for separate questions so other users can find it. This topic is "golf ball a certain distance".