Search Unity

How change object direction after collision?

Discussion in '2D' started by UrsinhoMalvado, Jul 31, 2018.

  1. UrsinhoMalvado

    UrsinhoMalvado

    Joined:
    Jun 30, 2018
    Posts:
    8
    I'm learning and in this process I'm creating a Block Breaker game.

    Some times the ball hits the left wall and the top of the paddle and the right wall in loop.

    Eventually the gravity kills the loop.

    I was wondering if there are a way to change the angle the ball kicks from a wall, so I can speedup the end of the loop.

    I tried to change the ball position but would be better to change the angle.

    Code (CSharp):
    1. if (collision.gameObject.tag != "Block")
    2.             {
    3.                hit++;
    4.  
    5.              
    6.                 if (hit > 8)
    7.                 {
    8.                     transform.position = new Vector2(transform.position.x + (Random.Range(-0.2f, 0.2f)), transform.position.y);
    9.                     hit = 0;
    10.  
    11.                 }
    12.             }
    13.             else
    14.             {
    15.                 hit = 0;
    16.            
    17.             }
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    It's not very clear what is happening from your description, usually there is no gravity in brick breaker games.

    Looks like for every hit that's not a block, you want to change something. How do you want the angle to change? Is it the angle you want to change? or the speed? gravity?

    You can get access to the current speed & direction of the ball using the rigidbody's velocity vector:
    float speed = rigidbody2D.velocity.magnitude;

    Vector2 direction = rigidbody2D.velocity.normalized;


    You can change the speed or the direction, and then multiply them together again as the new velocity. Just make sure you keep the direction normalized or you will change the speed when you multiply.
     
  3. UrsinhoMalvado

    UrsinhoMalvado

    Joined:
    Jun 30, 2018
    Posts:
    8
    I think if I change the velocity with
    GetComponent<Rigidbody2D>().velocity = new Vector2(xPush + 2, yPush);

    and later return to the normal value
    GetComponent<Rigidbody2D>().velocity = new Vector2(xPush, yPush);

    I can have what I was looking for and the velocity / direction will return to normal. Am I correct?

    Code (CSharp):
    1. private void OnCollisionEnter2D(Collision2D collision)
    2. {
    3.     if (hasStarted == true)
    4.     {
    5.  
    6.         if (collision.gameObject.tag != "Block")
    7.         {
    8.             hit++;
    9.  
    10.  
    11.             if (hit > 8)
    12.             {
    13.  
    14.                 GetComponent<Rigidbody2D>().velocity = new Vector2(xPush + 2, yPush);
    15.  
    16.                 hit = 0;
    17.  
    18.             }
    19.         }
    20.         else
    21.         {
    22.             hit = 0;
    23.  
    24.         }
    25.  
    26.         if (collision.gameObject.tag == "Paddle" || collision.gameObject.tag == “Block”)
    27.         {
    28.             GetComponent<Rigidbody2D>().velocity = new Vector2(xPush, yPush);
    29.  
    30.         }
    31.     }
    32.  
    33. }
    34.  
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    You'll definitely want to keep a class-level reference to Rigidbody2D, and assign it at Awake or Start, so you don't have to keep calling GetComponent every collision.

    With that logic, on the 9th collision with a "block", the X velocity will increase by 2. What does "xPush" and "yPush" represent? Do those values change?

    That also doesn't take into consideration if the ball has a negative velocity (going left).

    If you just straight up want to add 2 to the horizontal velocity, you should check if the horizontal velocity is positive or negative, and then apply the extra speed in that direction.
    Code (CSharp):
    1. Vector2 newVelocity = rigidbody.velocity;
    2. newVelocity.x += Mathf.Sign(newVelocity.x) * 2;
    3. rigidbody.velocity = newVelocity;
    Again, I'm still not sure what the actual behavior you're looking for is, if you could give a more detailed description it would be easier to understand your issues.
     
    Last edited: Aug 1, 2018
  5. UrsinhoMalvado

    UrsinhoMalvado

    Joined:
    Jun 30, 2018
    Posts:
    8
    I don't know how to insert an image here, so, follow this link for the image: https://imgur.com/a/dsrqSBf

    I hope this explain better what I'm trying to achieve.

    I tried your last suggestion but the ball becomes faster and faster. The ball speed must return to the normal pace after that.

    Thank you for your patience.
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Thanks for the images, I think I understand what you're trying to do.

    There's lots of different ways to solve this. If you don't want the ball to speed up at all, then changing the direction is your best bet.

    It's a bit tricky, because it's hard to know how much to change the angle by. If the ball is hitting only walls for awhile, then the direction is very horizontal. So if you want to make the movement direction jump up by like 45 degrees or something, you can try this (untested):

    Code (CSharp):
    1. public class example : MonoBehaviour
    2. {
    3.     private Rigidbody2D rb2D;
    4.     private bool hasStarted;
    5.     private int hit;
    6.  
    7.     private void Awake()
    8.     {
    9.         rb2D = GetComponent<Rigidbody2D>();
    10.     }
    11.  
    12.     private void OnCollisionEnter2D(Collision2D collision)
    13.     {
    14.         if (hasStarted)
    15.         {
    16.             if (collision.gameObject.tag != "Block")
    17.             {
    18.                 hit++;
    19.  
    20.                 if (hit > 8)
    21.                 {
    22.                     Vector2 currentDirection = rb2D.velocity.normalized;
    23.  
    24.                     // get a direction halfway between the ball's movement direction and straight up
    25.                     Vector2 newDirection = (currentDirection + Vector2.up).normalized;
    26.  
    27.                     rb2D.velocity = rb2D.velocity.magnitude * newDirection;
    28.                  
    29.                     hit = 0;
    30.                 }
    31.             }
    32.             else
    33.             {
    34.                 hit = 0;
    35.             }
    36.         }
    37.     }
    38. }

    If this makes your ball bounce the wrong direction off the wall, you can try using "OnCollisionExit2D" instead, OR add this line after "newDirection" is set:
    newDirection = Vector2.Reflect(newDirection, Vector2.up);
     
    UrsinhoMalvado likes this.
  7. UrsinhoMalvado

    UrsinhoMalvado

    Joined:
    Jun 30, 2018
    Posts:
    8
    Thank you! This solution looks work nicely!
     
    LiterallyJeff likes this.