- Home /
2D RPG style knockback on attack
Hello everyone, I am developing a top down RPG and I have implemented an action attack system. The player can deal damage and recieve, but the problem is that there is no knowckback when the player or the enemy is getting attacked, this is the script of the player controller:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
Rigidbody2D rbody;
Animator anim;
GameObject attackingZone;
public GameObject damageNumber;
public bool canMove;
public bool isAttacking;
public Stats stats;
public float attackRate;
public float nextAttack;
// Use this for initialization
void Start () {
rbody = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
attackingZone = transform.GetChild(0).gameObject;
stats = GetComponent<Stats>();
isAttacking = false;
attackRate = 0.5f;
nextAttack = 0.0f;
}
// Update is called once per frame
void Update () {
if(!canMove)
{
rbody.velocity = Vector2.zero;
return;
}
Vector2 movement_vector = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
if (movement_vector != Vector2.zero)
{
anim.SetBool("iswalking", true);
anim.SetFloat("input_x", movement_vector.x);
anim.SetFloat("input_y", movement_vector.y);
}
else
{
anim.SetBool("iswalking", false);
}
if(Input.GetKey(KeyCode.C) && Time.time > nextAttack)
{
anim.SetBool("isattacking", true);
nextAttack = Time.time + attackRate;
isAttacking = true;
}
else
{
isAttacking = false;
anim.SetBool("isattacking", false);
}
rbody.MovePosition(rbody.position + movement_vector * Time.deltaTime);
}
}
And the enemy script: using UnityEngine; using System.Collections;
public class SlimeController : MonoBehaviour {
public float moveSpeed;
public float timeBetweenMove;
public float timeToMove;
private Rigidbody2D rigidBody;
public bool moving;
private float timeBetweenMoveCounter;
private float timeToMoveCounter;
private Vector3 moveDirection;
private Stats stats;
private PlayerMovement player;
// Use this for initialization
void Start () {
rigidBody = GetComponent<Rigidbody2D>();
stats = GetComponent<Stats>();
player = GameObject.Find("Player").GetComponent<PlayerMovement>();
//timeBetweenMoveCounter = timeBetweenMove;
//timeToMoveCounter = timeToMove;
timeBetweenMoveCounter = Random.Range(timeBetweenMove * 0.75f, timeBetweenMove * 1.25f);
timeToMoveCounter = Random.Range(timeToMove * 0.75f, timeBetweenMove * 1.25f);
}
// Update is called once per frame
void Update () {
Debug.Log(rigidBody.velocity.x);
if(moving)
{
timeToMoveCounter -= Time.deltaTime;
rigidBody.velocity = moveDirection;
if(timeToMoveCounter < 0f)
{
moving = false;
//timeBetweenMoveCounter = timeBetweenMove;
timeBetweenMoveCounter = Random.Range(timeBetweenMove * 0.75f, timeBetweenMove * 1.25f);
}
}
else
{
timeBetweenMoveCounter -= Time.deltaTime;
rigidBody.velocity = Vector2.zero;
if (timeBetweenMoveCounter < 0f)
{
moving = true;
//timeToMoveCounter = timeToMove;
timeToMoveCounter = Random.Range(timeToMove * 0.75f, timeBetweenMove * 1.25f);
moveDirection = new Vector3(Random.Range(-1f, 1f) * moveSpeed, Random.Range(-1f, 1f) * moveSpeed, 0f);
}
}
}
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.name == "Player")
{
other.gameObject.GetComponent<Stats>().currentHP -= stats.attack;
var clone = (GameObject)Instantiate(player.damageNumber, other.transform.position, Quaternion.Euler(Vector3.zero));
clone.GetComponent<FloatingNumbers>().damageNumber = stats.attack;
}
}
}
Please help I really don't know how to do it.
First problem is that you set the RB'S velocity to moveDirection or zero, so any kind of behavior simulated by the Physics engine is overridden. Secondly, to push a character back, use RigidBody.AddForce or RigidBody.AddExplosionForce.
I understand, but thats the way my enemies' moving work, or do I have to change that? So how can I make my enemies move without setting the RB's velocity to these vectors? And can you explain how can I use AddForce?
I just noticed that AddExplosionForce is not available for RigidBody2D, so you'd have to use one of the RB2D AddForce functions.