- Home /
How to add knockback when player hit enemy 2D Platformer
Hi, 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):
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) Fighiting 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!");
}
}
Ok, I know what is messed - probably. When i hit play and see all my Enemies EnemyRB field which is Script field... and all of them are set to one of enemies. There is no uniqe scripts of any charcter.
When i delete one, the rest get the scripts from another one... Anyone knows how to fix this.