简体   繁体   中英

Unity 2D. Add knockback effect when my player hits enemy

I'm programming 2D Platformer I had problem/issue/weird situation - name it like you want. First of all, on my base Scene I have 4 Blobs (like on picture):

View from my Scene:

从我的场景中查看

The thing is: When I hit the biggest one it gets damage bo no knockback, the smaller one above got knock back effect and no damage. Every one of them are on Enemy Tag and Enemy Layer.

Funny Thing - when only one of them is on Enemy Layer and Tag, it gets correct effect (damage + knockback). Is it scripting issue or I messed something up in Unity.

PS. Another Funny Thing - when I set every Blob being on Enemy Layer and Tag. And I hit directly (and exactly) the one above me (with yellow arrow). It behaves correctly... So I'm even move confused.

My Code (Sorry it's compacted to one big file because of testing) Fighting and Moving


[PlayerControls.cs] :

using System.Collections;


using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Events;
 using UnityEngine.UI;
 using UnityEngine.Animations;
 using UnityEngine.SceneManagement;

 public class PlayerControls : MonoBehaviour
 {
     private float moveHoriz;
     public float speed;
     public bool grounded;


 private float crouch;
 public bool crouching;

 private Rigidbody2D rb;

 bool sliding;
 public float slideTimer;
 public float maxSlideTime;

 public float jumpForce;

 public bool facingRight = true;

 public bool isDoubleJump = true;

 public LayerMask whatIsGround;
 public float groundRadius;
 public Transform GroundCheck;

 public Transform CeilingCheck;
 private bool ceiled;

 public Transform NearGroundCheck;
 private bool isGroundNear;

 private int extraJumps;
 public int extraJumpValues;

 private bool jumping;

 private bool attack1;
 private bool attack2;
 private bool attack3;

 private bool airAttack1;

 public bool goodOrder1;
 public bool goodOrder2;
 public bool goodOrder3;

 public bool badOrder2;
 public bool badOrder3;

 public bool combo;
 public float comboDuration;
 public float comboEndup = 1;

 private bool shootBow;
 public bool reloadBow = true;
 public int reloadTime = 1;

 public Transform attackPos;
 public float attackRange;
 public LayerMask whatIsEnemy;
 public int damage;

 private EnemyScript enemy;

 public Animator animator;

 // Use this for initialization
 void Start()
 {
     extraJumps = extraJumpValues;
     rb = GetComponent<Rigidbody2D>();
     enemy = GameObject.FindGameObjectWithTag("Enemy").GetComponent<EnemyScript>();
 }


 // Update is called once per frame
 void Update()
 {
     animator.SetFloat("Speed", Mathf.Abs(moveHoriz));
     animator.SetBool("Grounded", grounded);
     animator.SetFloat("vertSpeed", rb.velocity.y);
     animator.SetInteger("isDoubleJump", extraJumps);

     animator.SetBool("Crouch", crouching);

     animator.SetBool("isSliding", sliding);
     animator.SetFloat("stopSliding", slideTimer);

     animator.SetBool("isGroundNear", isGroundNear);

     animator.SetBool("comboAttack", combo);
     animator.SetFloat("comboDuration", comboDuration);

     animator.SetBool("reloadBow", reloadBow);
     animator.SetFloat("reloadTime", reloadTime);

     animator.SetBool("goodOrder1", goodOrder1);
     animator.SetBool("goodOrder2", goodOrder2);
     animator.SetBool("goodOrder3", goodOrder3);

     animator.SetBool("badOrder2", badOrder2);
     animator.SetBool("badOrder3", badOrder3);

     moveHoriz = Input.GetAxisRaw("Horizontal");

     crouch = Input.GetAxisRaw("Crouch");

     RangeAttack();

     OrderCheck();

     Crouch();

     if (grounded != true)
     {
         jumping = true;
         sliding = false;
         slideTimer = 0;
     }

     if (grounded == true)
     {
         jumping = false;
         extraJumps = extraJumpValues;
     }

     if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps > 0)
     {
         jumping = true;
         rb.velocity = Vector2.up * jumpForce;
         extraJumps--;
     }
     else if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps == 0 && grounded == true)
     {
         rb.velocity = Vector2.up * jumpForce;
     }

     if (Input.GetKeyDown(KeyCode.H))
     {
         Die();
     }

 }

 void FixedUpdate()
 {
     grounded = Physics2D.OverlapCircle(GroundCheck.position, groundRadius, whatIsGround);

     ceiled = Physics2D.OverlapCircle(CeilingCheck.position, groundRadius, whatIsGround);

     isGroundNear = Physics2D.OverlapCircle(NearGroundCheck.position, groundRadius, whatIsGround); ;

     rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);



     Move();

     Flip();

     Sliding();

     Combo();

     HandleInput();

     HandleAttacks();

     DealDmg();

     ResetValues();
 }

 void Move()
 {
     rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);
 }

 // Flip (or better said Rotate) Character.
 void Flip()
 {
     if ((moveHoriz < 0 && facingRight == true) || (moveHoriz > 0 && facingRight == false))
     {
         facingRight = !facingRight;
         Vector3 theScale = transform.localScale;
         theScale.x *= -1;
         transform.localScale = theScale;
     }
 }

 void Crouch()
 {
     if ((crouch != 0 || ceiled == true) && grounded == true)
     {

         crouching = true;
     }
     else
     {
         crouching = false;
     }

     if (crouching)
     {
         speed = 10;
     }
     else
     {
         speed = 15;
     }
 }

 void Sliding()
 {
     //If statement to check if player is sliding to maxSlide capacity
     if (Input.GetButtonDown("Crouch") && speed > 0)
     {
         slideTimer = 0f;

         sliding = true;


         if (slideTimer >= maxSlideTime && sliding == true || moveHoriz == 0)
         {
             sliding = false;
             animator.SetBool("isSliding", false);
             crouching = true;
             animator.SetBool("Crouch", false);
         }
     }

     if (slideTimer < maxSlideTime && moveHoriz == 0 && crouch > 0)
     {
         sliding = false;

         animator.SetBool("isSliding", false);
         animator.SetBool("Crouch", true);

         crouching = true;
     }

     if (sliding)
     {
         speed = 25;
         slideTimer += Time.deltaTime;

         if (slideTimer >= maxSlideTime || jumping == true)
         {
             sliding = false;
             animator.SetBool("isSliding", false);
             speed = 15;
         }

         if (facingRight == true)
         {
             rb.velocity = Vector2.right * speed;
         }
         else if (facingRight != true)
         {
             rb.velocity = Vector2.left * speed;
         }
     }
 }

 void HandleAttacks()
 {
     if (attack1 == true)
     {
         goodOrder1 = true;
         goodOrder2 = false;
         goodOrder3 = false;
     }

     if (attack2 == true)
     {
         goodOrder1 = false;
         goodOrder2 = true;
         goodOrder3 = false;
     }

     if (attack3 == true)
     {
         goodOrder1 = false;
         goodOrder2 = false;
         goodOrder3 = true;
     }

     if (airAttack1)
     {
         animator.SetTrigger("airAttack1");
         attackRange = 1;
     }

 }

 private void HandleInput()
 {
     if (Input.GetButtonDown("Attack1"))
     {
         attack1 = true;
     }
     else if (Input.GetButtonUp("Attack1"))
     {
         attack1 = false;
     }

     if (Input.GetButtonDown("Attack2"))
     {
         attack2 = true;
     }
     else if (Input.GetButtonUp("Attack2"))
     {
         attack2 = false;
     }

     if (Input.GetButtonDown("Attack3"))
     {
         attack3 = true;
     }
     else if (Input.GetButtonUp("Attack3"))
     {
         attack3 = false;
     }



     if (grounded == false && (Input.GetButtonDown("Attack1") || Input.GetButtonDown("Attack2") || Input.GetButtonDown("Attack3")))
     {
         airAttack1 = true;
         attack1 = false;
     }

     if (airAttack1 == true && grounded == true)
     {
         airAttack1 = false;
     }
 }

 void OrderCheck()
 {
     // First sequence attack
     if (grounded == true && attack1 == true && comboDuration > 0)
     {
         goodOrder1 = true;
     }
     else if (goodOrder1 != true && grounded == true && attack2 == true && comboDuration <= 0)
     {
         badOrder2 = true;
     }

     // Second sequence attack
     if (grounded == true && attack2 == true && comboDuration > 0)
     {
         goodOrder2 = true;
     }
     else if (goodOrder1 != true && grounded == true && attack3 == true && comboDuration <= 0)
     {
         badOrder3 = true;
     }

     // Third sequence attack
     if (grounded == true && attack3 == true && comboDuration > 0)
     {
         goodOrder3 = true;
     }
     else if (goodOrder2 != true && grounded == true && goodOrder1 != true && comboDuration > 0)
     {
         badOrder3 = true;
     }

     // Clear if badOrder's achived
     if (badOrder2 == true || badOrder3 == true)
     {
         goodOrder1 = false;
         goodOrder2 = false;
         goodOrder3 = false;
     }
 }

 void Combo()
 {
     if (attack1 == true)
     {
         comboDuration = comboEndup;
     }

     /*if ((goodOrder1 == true || goodOrder2 == true || goodOrder3 == true) || (badOrder2 == true || badOrder3 == true))
     {
         comboDuration = comboEndup;
     }*/


     // comboEndup = 1; - reminder

     if (comboDuration > 0)
     {
         comboDuration -= Time.deltaTime;

         combo = true;
     }

     if (comboDuration <= 0 || (badOrder2 == true || badOrder3 == true))
     {
         comboDuration = 0;

         combo = false;

         goodOrder1 = false;
         goodOrder2 = false;
         goodOrder3 = false;

         badOrder2 = false;
         badOrder3 = false;
     }
 }

 void ResetValues()
 {
     if (badOrder2 == true || badOrder3 == true)
     {
         badOrder2 = false;
         badOrder3 = false;
     }

     airAttack1 = false;

     if (gameObject.GetComponent<PlayerControls>().grounded == true && airAttack1 == true)
     {
         airAttack1 = false;
     }
 }

 private void RangeAttack()
 {
     if (grounded == true && Input.GetButtonDown("Ranged"))
     {
         animator.SetTrigger("shootBow");
         reloadBow = false;

         attack1 = false;
         attack2 = false;
         attack3 = false;
     }
 }

 void OnDrawGizmosSelected()
 {
     Gizmos.color = Color.red;
     Gizmos.DrawWireSphere(attackPos.position, attackRange);
 }

 public void DealDmg()
 {
     if (attackPos.gameObject.activeSelf == true)
     {
         Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
         for (int i = 0; i < enemiesToDamage.Length; i++)
         {


             enemiesToDamage[i].GetComponent<EnemyScript>().TakeDmg(damage);


             if (facingRight == true)
             {
                 gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + transform.right * 500);
             }
             else if (facingRight == false)
             {
                 gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + (transform.right * 500) * -1);
             }

             attackPos.gameObject.SetActive(false);
         }
     }
 }

 void Die()
 {
     SceneManager.LoadScene(0);
 }
 }

Enemy Movement [EnemyScript.cs]:

    using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;

 public class EnemyScript : MonoBehaviour {

     public float speed;
 public float distance;

 public int health;

 public bool movingRight = true;

 public Transform groundDetection;

 public Rigidbody2D EnemyRB;

 public bool trap;
 public LayerMask TrapLayer;
 public Transform ColideDetector;
 public float detectorRadius;

 public BoxCollider2D CheckHeadBounce;

 // Use this for initialization
 void Start ()
 {
     EnemyRB = gameObject.GetComponent<Rigidbody2D>();
 }

 // Update is called once per frame
 void Update ()
 {
     trap = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, TrapLayer);

     if (health <= 0)
     {
         Destroy(gameObject);
     }

     transform.Translate(Vector2.right * speed * Time.deltaTime );

     RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);


     if (groundInfo.collider == false || trap == true)
     {
         if(movingRight == true)
         {
             transform.eulerAngles = new Vector3(0, -180, 0);
             movingRight = false;
         }
         else
         {
             transform.eulerAngles = new Vector3(0, 0, 0);
             movingRight = true;
         }
     }
 }

 public void HeadBounce()
 {

 }

 public void TakeDmg(int damage)
 {
     health -= damage;

     Debug.Log("damage TAKEN!");
 }

}

It's a gif to show what is going on

PlayerInspector - PlayerScript

Enemy Inspector - EnemyScript

You don't use the right reference of EnemyScript inside DealDmg . In the loop, you first call TakDmg on the enemy found from OverlapCircleAll , then you call AddForce on gameObject.GetComponent<EnemyScript>().EnemyRB .

Within this context, gameObject refer to the GameObject the running script is attached to ( PlayerControl.cs here). You need to apply the force on the rigidbody of the gameobject inside the collision array enemisToDamage , just like you did with TakeDmg .

Here is a possible solution.

public void DealDmg()
{
    if (attackPos.gameObject.activeSelf == true)
    {
        Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
        for (int i = 0; i < enemiesToDamage.Length; i++)
        {
            EnemyScript enemyScript = enemiesToDamage[i].GetComponent<EnemyScript>();
            enemyScript.TakeDmg(damage);
            if (facingRight == true)
            {
                enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + transform.right * 500);
            }
            else if (facingRight == false)
            {
                enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + (transform.right * 500) * -1);
            }
            attackPos.gameObject.SetActive(false);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM