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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

[SOLVED] Changing the sprite one second after hitting the walls

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

  1. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Hey

    I have two pictures: sprite1 and sprite2.

    I created a script that allows me to change a sprite every time when it hits a enemy or boundary (I added four box colliders 2d to the background that imitate the walls).

    The picture changes after every hit.

    How can I change the script so that after hitting the wall, the sprite1 changes into the sprite2 (as it is now), but after 1 second it returns to the sprite1.

    With the script that I wrote the first picture (sprite1) changes into the second (sprite2) after hitting the wall and the second (sprite2) in the first (sprite1) only after the next hit in the wall.

    PS: I am a beginner in c sharp, so the script can be a little "dirty" (badly written).
    PS2: Pmove is a script name :) [don't ask me why ]
    PS3: Thank you for every possible answer.

    My script:

    public class Pmove : MonoBehaviour {

    public Sprite sprite1;
    public Sprite sprite2;


    private SpriteRenderer spriteRenderer;

    void Start ()
    {
    spriteRenderer = GetComponent<SpriteRenderer>();

    if (spriteRenderer.sprite == null)
    spriteRenderer.sprite = sprite1;
    }

    void OnCollisionEnter2D (Collision2D whatHitMe)
    {
    if (whatHitMe.gameObject.tag == "Background") {
    ChangeTheDamnSprite ();
    } else {
    if (whatHitMe.gameObject.tag == "Enemy")
    ChangeTheDamnSprite ();
    }
    }

    void ChangeTheDamnSprite ()
    {
    if (spriteRenderer.sprite == sprite1)
    {
    spriteRenderer.sprite = sprite2;
    }
    else
    {
    spriteRenderer.sprite = sprite1;
    }
    }
    }
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    For something very simple like that, you could use 'Invoke'.
    Code (csharp):
    1. ChangeTheDamnSprite();
    2. Invoke("ChangeTheDamnSprite", 1);
    However, that might lead to an issue if you run into more things before 1 second passes.
    What would you want to happen if you were already waiting for a change back and hit something?
     
    polan31 likes this.
  3. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Nothing, because I want the sprite change to be an imitation of animation.

    Something like regular animation.

    Sprite1 hits the wall, turns into a picture that show "hitting the wall" and returns to the first picture.

    I tried to do it with the help of animation, but there were still problems, because it was impossible to stop the animation :)

    So I thought I would try to do it with the help of a script.

    Thanks for the answer. I will try to check and give an answer about the effects.

    PS: I'm sorry for my English, I'm not from english speaking country.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay -- so, if you hit a wall and it changes sprites, and you hit a wall again before having changed back to the original sprite, you don't do anything with the second wall?

    If that's the case, perhaps this is more sensible:
    Code (csharp):
    1. Coroutine changeSpriteRoutine;
    2. WaitForSeconds wfs = new WaitForSeconds(1f);
    3.  
    4. void OnCollisionEnter2D (Collision2D whatHitMe)
    5. {
    6.    GameObject g = whatHitMe.gameObject;
    7.    if (g.CompareTag("Background") || g.CompareTag("Enemy"))
    8.    {
    9.       if(changeSpriteRoutine == null)
    10.          changeSpriteRoutine = StartCoroutine(ChangeTheDamnSprite());
    11.    }
    12. }
    13. IEnumerator ChangeTheDamnSprite() {
    14.    spriteRenderer.sprite = sprite2;
    15.    yield return wfs;
    16.    spriteRenderer.sprite = sprite1;
    17.    changeSpriteRoutine = null;
    18. }
    I think that should work for ya.

    If you have any questions, feel free to ask.
     
    polan31 likes this.
  5. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Thank you. If you can, I will ask one more question.

    The Sprite I wrote about, after bouncing, rotates 90 degrees in the direction of movement.

    However, after writing the script and starting the game for unknown reasons, the sprite is rotated before hit.

    The sprite is still moving in the right direction .

    Just picture is inverted.

    Could you tell what is the reason for this?

    For a better understanding, I put below the pictures illustrating what is going on. The first picture (PIC I) shows how it looks before pressing the "star", the second picture (PIC II) after pressing the "start" button.

    Its my simple code:

    void Update() {

    rb.velocity = constantSpeed * (rb.velocity.normalized);

    // Make it look in direction of travel

    float angle = Mathf.Atan2(rb.velocity.y, rb.velocity .x) * Mathf.Rad2Deg;

    rb.rotation = angle - 90;


    PS: Thank you so much for your earlier answer, the code works amazing !! :)
     

    Attached Files:

  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I think this works..
    Code (csharp):
    1. public class Test1 : MonoBehaviour {
    2.     Rigidbody2D rb;
    3.     // stored in fixed update, to be used in OnCollisionEnter (which may have an altered value).
    4.     Vector2 currSpeed;
    5.     void Awake()
    6.     {
    7.         rb = GetComponent<Rigidbody2D>();
    8.     }
    9.     void FixedUpdate()
    10.     {
    11.         currSpeed = rb.velocity = transform.right;
    12.        
    13.     }
    14.     void OnCollisionEnter2D(Collision2D collision)
    15.     {
    16.         transform.right = Vector2.Reflect(currSpeed, collision.contacts[0].normal);
    17.     }
    18.  
    19. }
    20.  
    Little different than your code, but the same general idea. ;)

    You may have to subtract 90 like in your code, if the game object/sprite isn't pointing "right is forward".

    Edit: updated code / fixed some bugs.
     
    Last edited: Apr 4, 2018
    polan31 likes this.
  7. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Not really work because the sprite either falls behind the screen or is not visible, or moves to the right but I'll work a bit on it. It's an amazing starting point :)

    For now, I've made it to something like that:


    public class Test1: MonoBehaviour {
    Rigidbody2D rb;
    float constantSpeed = 10f;
    // stored in fixed update, to be used in OnCollisionEnter (which may have an altered value).
    Vector2 currSpeed;


    void Awake () {
    rb = GetComponent<Rigidbody2D> ();
    rb.velocity = new Vector2 (6f, 6f);
    }


    void FixedUpdate()

    {

    currSpeed = rb.velocity = constantSpeed * (rb.velocity.normalized);

    }
    void OnCollisionEnter2D(Collision2D collision)
    {
    rb.velocity = Vector2.Reflect(currSpeed, collision.contacts[0].normal);
    rb.rotation = 90;

    }
    }



    In this form it works pretty good, but the rotation only works once, after the first hit against the walls.

    I''ll change something tomorrow and give an answer as it finally looks;)
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, well perhaps I didn't understand your goals. I tested the code I wrote just for bouncing off the wall a few times and it looked good.
    Anyways, hope ya get it working. :)
     
    polan31 likes this.
  9. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Ok, I only changed:


    rb.rotation = 90;
    on

    rb.rotation += 90;

    but now it only rotates one way.

    For example: when the bullet bounces against the walls and goes to the right, it rotates 90 degrees to the right, but when it bounces to the left it also rotates 90 degrees to the right (IT SHOULD BE LEFT), which is not consistent with the direction of movement.

    I tried to replace it with:


    rb.MoveRotation(Mathf.LerpAngle(rb.rotation,rb.rotation+90,1));

    or

    Time.fixedDeltaTime;

    but it does not work.

    Any advice??
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Well, are you sure this code wasn't working for you?
    Code (csharp):
    1.  
    2. void OnCollisionEnter2D(Collision2D collision)
    3. {
    4.     transform.right = Vector2.Reflect(currSpeed, collision.contacts[0].normal);
    5. }
    In your last posted code, you're setting the rotation explicitly which isn't right.
     
    polan31 likes this.
  11. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149

    Okay
    Because you're still helping me, and I think I'm spoiling something, I've prepared a quick video to show you what the problem is :)

    First of all, I use this code:

    Code (CSharp):
    1. public class Test1: MonoBehaviour {
    2.  
    3.     Rigidbody2D rb;
    4.  
    5.     float constantSpeed = 10f;
    6.  
    7.     // stored in fixed update, to be used in OnCollisionEnter (which may have an altered value).
    8.  
    9.     Vector2 currSpeed;
    10.  
    11.  
    12.  
    13.  
    14.  
    15.     void Awake () {
    16.  
    17.         rb = GetComponent<Rigidbody2D> ();
    18.  
    19.         rb.velocity = new Vector2 (6f, 6f);
    20.  
    21.     }
    22.  
    23.  
    24.  
    25.    
    26.  
    27.     void FixedUpdate()
    28.  
    29.  
    30.  
    31.             {
    32.  
    33.  
    34.  
    35.         currSpeed = rb.velocity = constantSpeed * (rb.velocity.normalized);
    36.  
    37.  
    38.  
    39.         }
    40.  
    41.         void OnCollisionEnter2D(Collision2D collision)
    42.  
    43.         {
    44.  
    45.         rb.velocity = Vector2.Reflect(currSpeed, collision.contacts[0].normal);
    46.  
    47.         rb.rotation += 90;
    48.  
    49.  
    50.  
    51.         }
    52.  
    53. }
    Okay, I put a video like a bullet behaves after colliding with a wall and how it behaves after hitting an enemy :) I hope it will help :)



     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, well what if you try the code I posted?
     
    polan31 likes this.
  13. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    I don't know exactly what code we're talking about because I've already got a little lost :)

    But when it comes to this code:

    Code (CSharp):
    1. public class Test1 : MonoBehaviour {
    2.     Rigidbody2D rb;
    3.     // stored in fixed update, to be used in OnCollisionEnter (which may have an altered value).
    4.     Vector2 currSpeed;
    5.     void Awake()
    6.     {
    7.         rb = GetComponent<Rigidbody2D>();
    8.     }
    9.     void FixedUpdate()
    10.     {
    11.         currSpeed = rb.velocity = transform.right;
    12.      
    13.     }
    14.     void OnCollisionEnter2D(Collision2D collision)
    15.     {
    16.         transform.right = Vector2.Reflect(currSpeed, collision.contacts[0].normal);
    17.     }
    18.  
    19. }
    Bullet moves only to the right and left :
     
  14. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ah okay, well aside from the code not giving you more speed (easily fixed), it seems that your sprite is diagonal by default, not by rotation.

    Plus, is that 2 different colliders (non-trigger?)
     
    polan31 likes this.
  15. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    No, no :) The bullet is supposed to look like this because it is shot at this angle :) So with the look everything is fine, only with the movement something wrong :) Everything should look like in the previous post, it should only rotate in movement direction. If the ball bounces to the right, it must rotate 90 degrees to the right, but if the ball bounces to the left, it should rotate to the left :)

    And yes - two differen colliders (non-trigger) :)
     
  16. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Uh huh.. Couldn't the sprite be horizontal, facing right & then rotated to be at the angle you have currently when you start? That's what I'm getting at.. that would be easier to work with/code, I think.
    You could try that, and see if it helps.

    You can attach a simple unity package to the thread if you're still stuck, and maybe I can look at it.
     
    polan31 likes this.
  17. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    With a horizontal sprite I don't have a problem because I used something similar in a different tutorial a few months ago when I started my adventure with Unity, now I just raised the level and wanted to learn it :) But if you have any advice, write and I will definitely use them :)
     
  18. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I'm saying you can make the sprite horizontal instead of slanted like that. But then you can change its rotation in code so it essentially looks the same, but is easier to work with...
    To me, it's a lot easier to follow if "pointing right" is actually the direction forward it's pointing?! :)
     
    polan31 likes this.
  19. polan31

    polan31

    Joined:
    Nov 20, 2017
    Posts:
    149
    Oh, you're talking about it :) I understood completely different things :) I'm sorry, but I'm not from English speaking country, so I dpn't fully understand the context of each statement :) Yes, in this case it actually makes sense and it could work :)
     
  20. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool.. I'm glad it makes sense, because I wasn't sure what was wrong :)

    At least try that to see what it looks like. Then, if any issues remain, it will be easier to work them out with that setup...
     
    polan31 likes this.