Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How to bounce the bullet?

Discussion in 'Scripting' started by polan31, Apr 24, 2018.

  1. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    I have bullet.

    My script allows me to:

    1) Move the ball around the screen with a mouse

    2) After pressing the left mouse button, hold the bullet, change the sprite and choose the rotation (place where it will fire)

    3) After pressing the right mouse button, shoot it.

    My problem?


    The bullet after shooting doesn't bounce off the walls and doesn't rotate (face) in the moving direction.



    My script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class NewFollow : MonoBehaviour {
    6.  
    7.         public Sprite sprite1; // Drag your first sprite here
    8.         public Sprite sprite2;
    9.         public float moveSpeed = 10f;
    10.         bool mouseClicked = false;
    11.         private SpriteRenderer spriteRenderer;
    12.         bool rightClicked = false;
    13.         private bool canClick = true;
    14.         public float speed;
    15.         public Rigidbody2D rb;
    16.  
    17.         // Use this for initialization
    18.  
    19.     void Start ()
    20.     {
    21.  
    22.         spriteRenderer = GetComponent<SpriteRenderer>(); // we are accessing the SpriteRenderer that is attached to the Gameobject
    23.         if (spriteRenderer.sprite == null) // if the sprite on spriteRenderer is null then
    24.             spriteRenderer.sprite = sprite1; // set the sprite to sprite1
    25.  
    26.         rb = GetComponent<Rigidbody2D>();
    27.  
    28.     }
    29.  
    30.     Coroutine changeSpriteRoutine;
    31.     WaitForSeconds wfs = new WaitForSeconds(0.05f);
    32.  
    33.     void OnCollisionEnter2D (Collision2D whatHitMe)
    34.     {
    35.         GameObject g = whatHitMe.gameObject;
    36.         if (g.CompareTag("Background") || g.CompareTag("Enemy"))
    37.         {
    38.             if(changeSpriteRoutine == null)
    39.                 changeSpriteRoutine = StartCoroutine(ChangeTheDamnSprite());
    40.             {
    41.  
    42.                 if (g.CompareTag("Background") || g.CompareTag("Enemy"))
    43.             {
    44.  
    45.                     float angle = Mathf.Atan2(rb.velocity.y, rb.velocity .x) * Mathf.Rad2Deg;
    46.                     rb.rotation = angle - 90;
    47.  
    48.  
    49.         }
    50.     }
    51.         }
    52.     }
    53.  
    54.     IEnumerator ChangeTheDamnSprite() {
    55.         spriteRenderer.sprite = sprite2;
    56.         yield return wfs;
    57.         spriteRenderer.sprite = sprite1;
    58.         changeSpriteRoutine = null;
    59.     }
    60.  
    61.     public void Update ()
    62.     {
    63.  
    64.         transform.position = Vector2.Lerp (transform.position, Camera.main.ScreenToWorldPoint (Input.mousePosition), moveSpeed);
    65.  
    66.         Vector3 difference = Camera.main.ScreenToWorldPoint (Input.mousePosition) - transform.position;
    67.         difference.Normalize ();
    68.  
    69.         {
    70.             if (canClick)
    71.             {
    72.                 if (Input.GetMouseButtonDown (0)) {
    73.                     Debug.Log ("Left Mouse Button was pressed");
    74.                     moveSpeed = 0f;
    75.                     if (spriteRenderer.sprite == sprite1) { // if the spriteRenderer sprite = sprite1 then change to sprite2
    76.                         spriteRenderer.sprite = sprite2;
    77.  
    78.                     }
    79.                     mouseClicked = true; //register that the mouse has been clicked and the sprite is changed to sprite2
    80.                     rightClicked = false;              
    81.                     canClick = false;
    82.                 }
    83.             }
    84.  
    85.         if (mouseClicked) {        //checks if sprite has already been changed
    86.             Vector3 mousePos = Input.mousePosition;        //gets the current mouse position on screen
    87.             int currentCase = 0;
    88.             //following does a case-check on the position of your mouse with respect to the sprite:
    89.             if (Camera.main.transform.position.x - (Screen.width/2) + mousePos.x < transform.position.x) {      
    90.                 if (Camera.main.transform.position.x - (Screen.height/2)+mousePos.y < transform.position.y) {
    91.                     currentCase = 2;
    92.                 } else {
    93.                     currentCase = 3;
    94.                 }
    95.             } else {
    96.                 if (Camera.main.transform.position.x - (Screen.height/2)+mousePos.y < transform.position.y) {
    97.                     currentCase = 1;
    98.                 } else {
    99.                     currentCase = 0;
    100.                 }
    101.             }
    102.             //create a new rotation:
    103.             transform.rotation = Quaternion.Euler (0, 0, 90 * currentCase);
    104.         }
    105.             {
    106.  
    107.                 if (Input.GetMouseButton(1)) {
    108.                     Debug.Log ("Pressed secondary button.");
    109.                     rightClicked = true;
    110.                     mouseClicked = false;
    111.  
    112.                 }
    113.                 if(rightClicked)
    114.  
    115.  
    116.                     transform.position += (transform.right + transform.up).normalized *  speed * Time.deltaTime;
    117.  
    118.             }
    119.         }
    120.     }
    121. }
    Could anyone fix my script? I am a bit desperate because I am improving it for weeks and I can not achieve anything.

    The whole situation can be seen in the video:

    Code (CSharp):
    1. https://gfycat.com/pl/gifs/detail/BothTerrificElephantbeetle
    PS: My bullet call is called "Pill".
     
  2. zakdank

    zakdank

    Joined:
    Jan 25, 2011
    Posts:
    46
    What you need to look at is Vector2.Reflect - https://docs.unity3d.com/ScriptReference/Vector2.Reflect.html.

    The basic premise is that when the bullet collides with the wall, it reflects it.

    I can't check it right now as I don't have time to open unity and play around but I did find this answer that may help - https://stackoverflow.com/a/41130841
    Code (CSharp):
    1. void OnCollisionEnter(Collision collision)
    2. {
    3.     Vector2D inDirection = GetComponent<RigidBody2D>().velocity;
    4.     Vector2D inNormal = collision.contacts[0].normal;
    5.     Vector2D newVelocity = Vector2D.Reflect(inDirection, inNormal);
    6. }
     
  3. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Ok. I changed the script a bit.

    My script now:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class NewFollow : MonoBehaviour {
    6.  
    7.         public Sprite sprite1; // Drag your first sprite here
    8.         public Sprite sprite2;
    9.         public float moveSpeed = 10f;
    10.         bool mouseClicked = false;
    11.         private SpriteRenderer spriteRenderer;
    12.         bool rightClicked = false;
    13.         private bool canClick = true;
    14.         public float speed;
    15.         public Rigidbody2D rb;
    16.     float constantSpeed = 10f;
    17.     // stored in fixed update, to be used in OnCollisionEnter (which may have an altered value).
    18.     Vector2 currSpeed;
    19.  
    20.         // Use this for initialization
    21.  
    22.     void Start ()
    23.     {
    24.  
    25.         spriteRenderer = GetComponent<SpriteRenderer>(); // we are accessing the SpriteRenderer that is attached to the Gameobject
    26.         if (spriteRenderer.sprite == null) // if the sprite on spriteRenderer is null then
    27.             spriteRenderer.sprite = sprite1; // set the sprite to sprite1
    28.  
    29.         rb = GetComponent<Rigidbody2D>();
    30.  
    31.     }
    32.  
    33.     Coroutine changeSpriteRoutine;
    34.     WaitForSeconds wfs = new WaitForSeconds(0.05f);
    35.  
    36.     void OnCollisionEnter2D (Collision2D whatHitMe)
    37.     {
    38.         GameObject g = whatHitMe.gameObject;
    39.         if (g.CompareTag("Background") || g.CompareTag("Enemy"))
    40.         {
    41.             if(changeSpriteRoutine == null)
    42.                 changeSpriteRoutine = StartCoroutine(ChangeTheDamnSprite());
    43.             {
    44.  
    45.                 if (g.CompareTag("Background") || g.CompareTag("Enemy"))
    46.                 {
    47.  
    48.                     rb.velocity = Vector2.Reflect(currSpeed, whatHitMe.contacts[0].normal);
    49.                     rb.rotation +=90;
    50.  
    51.         }
    52.     }
    53.         }
    54.     }
    55.  
    56.     IEnumerator ChangeTheDamnSprite() {
    57.         spriteRenderer.sprite = sprite2;
    58.         yield return wfs;
    59.         spriteRenderer.sprite = sprite1;
    60.         changeSpriteRoutine = null;
    61.     }
    62.  
    63.     public void Update ()
    64.     {
    65.  
    66.         transform.position = Vector2.Lerp (transform.position, Camera.main.ScreenToWorldPoint (Input.mousePosition), moveSpeed);
    67.  
    68.         Vector3 difference = Camera.main.ScreenToWorldPoint (Input.mousePosition) - transform.position;
    69.         difference.Normalize ();
    70.  
    71.         currSpeed = rb.velocity = constantSpeed * (rb.velocity.normalized);
    72.  
    73.         {
    74.             if (canClick)
    75.             {
    76.                 if (Input.GetMouseButtonDown (0)) {
    77.                     Debug.Log ("Left Mouse Button was pressed");
    78.                     moveSpeed = 0f;
    79.                     if (spriteRenderer.sprite == sprite1) { // if the spriteRenderer sprite = sprite1 then change to sprite2
    80.                         spriteRenderer.sprite = sprite2;
    81.  
    82.                     }
    83.                     mouseClicked = true; //register that the mouse has been clicked and the sprite is changed to sprite2
    84.                     rightClicked = false;              
    85.                     canClick = false;
    86.                 }
    87.             }
    88.  
    89.         if (mouseClicked) {        //checks if sprite has already been changed
    90.             Vector3 mousePos = Input.mousePosition;        //gets the current mouse position on screen
    91.             int currentCase = 0;
    92.             //following does a case-check on the position of your mouse with respect to the sprite:
    93.             if (Camera.main.transform.position.x - (Screen.width/2) + mousePos.x < transform.position.x) {      
    94.                 if (Camera.main.transform.position.x - (Screen.height/2)+mousePos.y < transform.position.y) {
    95.                     currentCase = 2;
    96.                 } else {
    97.                     currentCase = 3;
    98.                 }
    99.             } else {
    100.                 if (Camera.main.transform.position.x - (Screen.height/2)+mousePos.y < transform.position.y) {
    101.                     currentCase = 1;
    102.                 } else {
    103.                     currentCase = 0;
    104.                 }
    105.             }
    106.             //create a new rotation:
    107.             transform.rotation = Quaternion.Euler (0, 0, 90 * currentCase);
    108.         }
    109.             {
    110.  
    111.                 if (Input.GetMouseButton(1)) {
    112.                     Debug.Log ("Pressed secondary button.");
    113.                     rightClicked = true;
    114.                     mouseClicked = false;
    115.  
    116.                 }
    117.                 if(rightClicked)
    118.  
    119.  
    120.                     transform.position += (transform.right + transform.up).normalized *  speed * Time.deltaTime;
    121.  
    122.             }
    123.         }
    124.     }
    125. }

    I prepared a few code versions and in the best option(this code above), it looked like this:

    Code (CSharp):
    1. https://gfycat.com/pl/gifs/detail/EarnestDeliriousHarrierhawk
    Does anyone know how to make the bullet bounce normally? :)
     
  4. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    818
    What do you mean normally, what happens now and what do you want to happen?

    Try formatting your code a bit better, that will make it much easier to read.
     
  5. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Thanks for your answer.

    If you watched the video (to which I posted the link) you should understand what happens now ( what is wrong). ;)

    The ball after a moment of reflection is like "suspended".

    It is not easy to write, that's why I put a video.:confused:
     
    Last edited: Apr 25, 2018
  6. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    818
    Sorry, only watched the beginning.

    I'd really start by cleaning up your code, remove any unnecessary brackets and fix your indentation. Then add some debugging, put a debug log in your OnCollisionEnter to see when you reflect and when you dont. You can even use OnCollisionStay to determine when you keep colliding with the edges.
     
  7. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Thanks for good words ;)
    I know that my problem lies in this line:

    Code (CSharp):
    1. rb.velocity = Vector2.Reflect(currSpeed, whatHitMe.contacts[0].normal);
    2.                     rb.rotation +=90;
    My gameObject (bullet) should rotate 90 degrees in the direction of movement after each hit.

    I had a similar problem with another script and the situation was the same.

    Unfortunately, that script has long been deleted and I don't know how I solved that problem.:(

    Maybe you know another way how to rotate (my bullet) 90 degrees in the direction of moving after each bounce from the wall?

    PS: I'm sorry for English, I'm still learning ;)
     
  8. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    818
    Can you verify that that line is executed when it sticks?

    Add a debug log there and see if it happens when you think it does, and not too often.
     
  9. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Hi.

    I made a smaller circle collider that I had added to the face (in video YELLOW part) of the bullet and now it is not stuck, but the bullet falls out of the screen.

    I added Debu.Log to check and it detects everything - every hit and rotation.

    The same situation is when I exchange circle collider 2d for polygon collider 2d.

    That's how it looks now:

    Code (CSharp):
    1. https://gfycat.com/pl/gifs/detail/BadMiserlyFowl
     
  10. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    Code (CSharp):
    1.  rb.rotation +=90;
    Whats this for ?
    If you get wrong normal direction for what ever reason multiply it with -1.0f.
    Also consider reading the description of functions witch say you should use GetContacts instead of of contacts.
    Code (CSharp):
    1. ContactPoint2D[] myContact = new ContactPoint2D[1];
    2.     void OnCollisionEnter2D (Collision2D collider)
    3.     {
    4.         collider.GetContacts(myContact);
    5.         //do stuff with myContact[0].normal;
    6.         //or if the behavior is mirrored with (myContact[0].normal * -1.0f)
    7.     }
     
  11. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    I use it to rotate (gameObject - sprite called "Pill") 90 degrees in the direction of movement after each hit.
     
  12. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    I guess that's what you try to do.

    Code (CSharp):
    1.     float speed = 0.1f;
    2.     Vector2 direction = new Vector3(0.7f,0.7f);
    3.     ContactPoint2D[] myContact = new ContactPoint2D[1];
    4.  
    5.  
    6.     void OnCollisionEnter2D (Collision2D collider)
    7.     {
    8.         collider.GetContacts(myContact);
    9.         direction = Vector2.Reflect(direction, myContact[0].normal);
    10.         this.transform.rotation = Quaternion.LookRotation(new Vector3(direction.x,direction.y,0.0f));
    11.     }
    12.  
    13.  
    14.     public void Update ()
    15.     {
    16.         this.transform.position += new Vector3(direction.x,direction.y,0.0f) * speed;
    17.     }
    This works with rigid body set to kinematic.
     
    XellioGames likes this.
  13. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Thanks for this script, but I will look for another option.
    Sending rigidbody 2d to kinematic, will cause that the bullet won't bounce off the walls and I will have to make many changes in the script.

    In addition, the script has disabled bouncing with 90 degrees in the direction of movement after each hit.

    However, thank you for the script, maybe someday I will use it :)
     
  14. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    Actually the script lets the bullet bounce off walls it collides with.

    I also still do not get why you want to use + 90 degrees if your bullet is moving at a wall with a direction of 315 you will rotate it to 405 degree. Or when it fly's straight up at 0 degree and you rotate it +90 degrees it will fly parallel with the wall at 90 degree....
    degrees.jpg
    Also if for what ever reason you want 90 degree bounce don't use Vector2.Reflect instead go with cousins and sinus.
     
  15. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Because without rb.rotation +=90; there is no bullet rotation moment.

    The impact is detected, but there is no rotation.

    That's how it looks then:

    Code (CSharp):
    1. https://gfycat.com/pl/gifs/detail/FlakyPinkAmphiuma
    Also, with your corrections, I can't choose a place where I shoot.

    As you can see on the video, after pressing the left mouse button, I can choose four directions:
    1)up right
    2)down right
    3)down left
    4)up left

    When I add your script, the ball flies only in the up right direction.
     
    Last edited: Apr 26, 2018
  16. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    Only cause it looks more wrong without +90 it wont make +90 the right way to do it also it always moves top right cause the direction is set to 0.7,0.7... (cos and sin of 45°)

    Also the script is there to show you how to implement a bouncing object not to replace your whole code...
     
  17. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Ok, I think I know what's wrong but I do not know how to solve it.

    If I add to the rb.rotation "+" the bullet is reflected only in the right side (which causes stuck or fall out when it should bounce left).

    Analogous situation with a "-", but this time bullet reflected only left.

    However without "+" or "-" bullet doesn't bounce at all.
     
  18. BVGuled

    BVGuled

    Joined:
    Nov 25, 2017
    Posts:
    5
    please check the below code, apply it to bullet which should have rigidbody with gravity 0 and a circle collider 2d


    public float speed;

    private void Update()
    {
    transform.Translate(Vector2.up * Time.deltaTime * speed);
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
    if(collision.gameObject.tag == "wall")
    {
    ContactPoint2D point = collision.contacts[0];
    Vector2 newDir = Vector2.zero;
    Vector2 curDire = this.transform.TransformDirection(Vector2.up);

    newDir = Vector2.Reflect(curDire, point.normal);
    transform.rotation = Quaternion.FromToRotation(Vector2.up, newDir);
    }
    }
     
  19. Johan_Liebert123

    Johan_Liebert123

    Joined:
    Apr 15, 2021
    Posts:
    474
    Is that a solution or a problem??? o_O