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. Dismiss Notice

Question Need help correcting player knock back by enemy script

Discussion in 'Scripting' started by DTheChemist, Feb 5, 2023.

  1. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    What do i need to do further to make the player actually bounce back from colliding with the enemy?

    I made the codes properly with a debug message that pops up when their colliders touch but theres nothing happening where i can actually see the player being knocked back. i was trying to achieve that same Castlevania or even Ninja gaiden nes still knock back hit by enemies.

    Player collision script:

    Code (CSharp):
    1. public class PlayerCollision : MonoBehaviour
    2. {
    3.  
    4.     public float knockbackForce = 10f;
    5.     public Rigidbody2D rb;
    6.  
    7.     private void OnCollisionEnter2D(Collision2D collision)
    8.     {
    9.         if (collision.gameObject.tag == "Enemy")
    10.         {
    11.             Vector2 knockbackDirection = (rb.position - (Vector2)collision.transform.position).normalized;
    12.             rb.AddForce(knockbackDirection * knockbackForce, ForceMode2D.Impulse);
    13.             Debug.Log("Player hit by enemy");
    14.         }
    15.      
    16.     }
    17.  
    18.  
    19. }
    20.  

    And heres the enemy collision script:

    Code (CSharp):
    1. public class EnemyCollision : MonoBehaviour
    2. {
    3.     private void OnCollisionEnter2D(Collision2D collision)
    4.     {
    5.         if (collision.gameObject.tag == "Player")
    6.         {
    7.             Debug.Log("Enemy Hurt player!");
    8.         }
    9.     }
    10.  
    11.  
    12.  
    13. }

    All i need to know further is what am i missing in code or what steps i need to make further for the actual effect to trigger instead of just the debug message

    Thank you
     
  2. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    717
    Hmm, that looks reasonable to me.

    I would double-check that the force vector makes sense by drawing it:

    Debug.DrawRay(rb.position, knockbackDirection, Color.white, 1f);


    That should display a line for one second, starting at the player's position and pointing in the direction of the force. You'll need to have gizmos toggled on to see them (they're off by default in Play Mode).
     
    angrypenguin likes this.
  3. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    Thanks

    Ok i can see the line appear which is something for a start but still no actual knock back. i revised the code with a snippet i saved a while back. had to find it in my notes so now i can get bounce on the enemy head for a hit. which is ok for now but if can get push back from a collide horizontal and that, that would be better.


    Anyway, for your curiosity this is what the codes looks like now in the player script:


    Code (CSharp):
    1. bool hitSideRight;
    2.  
    3.     public float knockbackForce = 5f;
    4.     public Rigidbody2D rb;
    5.  
    6.  
    7.  
    8.     public void HitSide(bool rightSide)//
    9.     {
    10.         // determines the push direction of the hit animation
    11.         hitSideRight = rightSide;
    12.     }
    13.  
    14.     private void OnCollisionEnter2D(Collision2D collision)
    15.     {
    16.         if (collision.gameObject.tag == "Enemy")
    17.         {
    18.             Vector2 knockbackDirection = (rb.position - (Vector2)collision.transform.position).normalized;
    19.             rb.AddForce(knockbackDirection * knockbackForce, ForceMode2D.Impulse);
    20.             Debug.DrawRay(rb.position, knockbackDirection, Color.white, 1f);
    21.         }
    22.     }

    The enemy collision script revised:

    Code (CSharp):
    1. private void OnCollisionEnter2D(Collision2D collision)
    2.     {
    3.         if (collision.gameObject.tag == "Player")
    4.         {
    5.             PlayerCollision player = collision.gameObject.GetComponent<PlayerCollision>();
    6.             if (player != null)
    7.             {
    8.                 Vector2 knockbackDirection = (player.rb.position - (Vector2)collision.transform.position).normalized;
    9.                 player.rb.AddForce(knockbackDirection * player.knockbackForce, ForceMode2D.Impulse);
    10.                 player.HitSide(transform.position.x > player.transform.position.x);
    11.             }
    12.             Debug.Log("Player hit by enemy");
    13.         }
    14.     }

    for the record the right side Bool method i tried to emulate from what i saw in an old megaman get hit tutorial video. where walking into or jumping on top of an enemy you get a bounce knock back.... my poor attempt
     
  4. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    Heres a visual test of what im seeing
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    How are you driving the player's rigidbody?

    If you're just setting it's
    .velocity
    property each FixedUpdate then applying forces isn't going to do anything.
     
  6. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    it has a separate script for Playermovement not shown there with rigidbody in it if thats what youre wondering. thats how im driving the player. I assume i did that wrong? was the collision code supposed to be all in one code with the player movement is what you mean?
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    No what saying is, what methods are you using to move the rigidbody in your player controller? Are you adding forces? Are you mutating it's
    .velocity
    property? Are using
    Rigidbody.MovePosition()
    ?

    Not all the various methods are compatible with one another.
     
  8. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    I was trying to add forces just between the two scripts

    like this portion

    player.rb.AddForce(knockbackDirection * player.knockbackForce, ForceMode2D.Impulse);

    Im not keen on what methods are compatible with the other yet entirely

    i have nothing in fixed update between those two scripts. any suggestions?
     
  9. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    Two posts and you've yet to answer my question.

    I'll only ask one more time: how are moving your player's rigidbody in your player controller?
     
  10. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    then dont bother because at this point youre confusing me now.
     
  11. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    I genuinely don't understand what's confusing. I just want to know how you move the player's rigidbody with your player controller script.

    Like I said, some methods of moving rigid bodies aren't compatible with others. That's what I'm trying to suss out.

    If you can't answer this question you likely won't find a solution.
     
    chemicalcrux likes this.
  12. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    717
    If you set the velocity of the player's rigidbody every frame, then adding a force will not do anything, since you will instantly overwrite the rigidbody's old velocity with the player's input.
     
    spiney199 likes this.
  13. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115

    Youre confusing me because i dont know if youre talking about what am i trying to use in method to get the player's Rigidbody to move while hit during a collide OR are you talking literally how my player is moving back and forth to walk which i have in my player movement script so that it moves or jumps. If you mean that then its Velocity. If thats not what it is you are asking me then i dont know

    for example with jump my Rigibody with it using Velocity is

    Code (CSharp):
    1.  if (Input.GetButtonDown("Jump"))
    2.         {
    3.             rb.velocity = new Vector2(rb.velocity.x, jumpSpeed);
    4.  
    5.         }
    Other than that i went with the addforce method from the tutorials ive been trying to look at but its like half working
     
  14. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115

    yes im more so using Velocity (i guess) from My other script not shown which is the player movement script i made. there i more so use Velocity. The player collision and player movement scripts are separate. AddForce i honestly only tried to use with my collision scripts. so ultimately it sounds like you both are saying remove that addforce there and instead use Velocity?
     
  15. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    This. Your primary method of controlling your player (aka, your player controller) affects how other sources will have to be designed in order to influence it.

    Pretty much, as I said right at the beginning:
    If you're driving it through the
    .velocity
    property, then everything else is going to have to do the same.

    You're effectively in DIY territory as you're overriding/bypassing most of the rest of the rigidbody API.
     
  16. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,509
    Post the other script.

    The others are trying to determine whether or not you are doing something like...
    Code (csharp):
    1. rigidbody.velocity = something;
    ...in the script which you're not showing us.

    Because if you are, then that is overriding anything that you do in your knockback script.
     
  17. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    Thats what i was trying to tell them. its in my other script for the player movement to move back n forth. do you mean this?

    void FixedUpdate()
    {
    movement = new Vector2(mX * Speed, rb.velocity.y);


    rb.velocity = movement; <<<<<<-------- Here



    }


    in my collision script i was only using addforce because thats what i thought the proper method was from what i was following for situations like that. thats where the confusion for me was at. whether they meant Rigidbody moved doing a hit or during gamepad or keyboard moving the character etc
     
  18. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    Ok now i understand.

    I wasnt sure exactly what you were looking for but thats why i said before i may have something like that in the playermovement script i created separate which is different. I think this is the example you more so wanted to see (?)

    Code (CSharp):
    1. void FixedUpdate()
    2.     {
    3.         movement = new Vector2(mX * Speed, rb.velocity.y);
    4.    
    5.  
    6.        rb.velocity = movement;
    7.  
    8.    
    9.  
    10.     }
     
  19. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    In any case, this is most likely your path forward:
    This is potentially going to involve expanding your player controller API.
     
  20. DTheChemist

    DTheChemist

    Joined:
    Jan 18, 2021
    Posts:
    115
    Explain further what you mean, if you dont mind. is that a major task er somethin? Whats API?
     
    Last edited: Feb 7, 2023
  21. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    Programming in general is a bit of a task so you shouldn't shy away from a bit of work.

    API, ego Application Programming Interface, aka, a bunch of systems and methods exposed to users to interface with larger applications. You know, such as all the methods that Unity provides for us to interact with the engine, hence the scripting docs being called:
    upload_2023-2-7_13-39-30.png

    It's good practice to do it in your own systems. Expose methods that let other systems interact and tell it what to do so you can keep all the logic in one, reusable place

    In the context of a player controller, you can keep all the movement stuff internal to the one component, and have a bunch of public methods that let outside sources tell it how to move. Such as applying knock-back forces, etc.