I’m new to unity and after doing a tutorial I’m messing around with this idea for a game. In my game I want to be able to attack people and have those people be knocked back. So in my script I need to have ObjectA fly back in the direction ObjectB was facing when ObjectB attacked Object A.
I have two scripts that are involved. A script that handles the attack, and a script that handle the movement of players, inside that script is a function which is called when the player is knocked back. So far however, I’ve only been able to make the a played get knocked back based on the global values of XYZ. Seeing as I want the objects to fly backwards when hit, I want them to use the attacking objects Z axis. What I currently have is objects that fly down the global z axis no matter what direction they were hit in.
Here’s the Attack code that the knockback is called from, the knockback function takes a vector3 and applies it as velocity to a rigidbody. As you can see I use a Raycast to detect an enemy colider and do damage when in range. The attack function is called from an animation event. (The code is quite messy, sorry about all the commented parts)
using UnityEngine;
using System.Collections;
public class PlayerAttack : MonoBehaviour {
public int attackDamage = 10;
public float meleeRange = 1;
Animator anim;
GameObject enemy;
GameObject player;
PlayerHealth enemyHealth;
PlayerMovement2 enemyKnockback;
PlayerMovement2 playerMove;
Ray tarRay;
RaycastHit tarHit;
void Awake()
{
anim = GetComponent<Animator>();
playerMove = GetComponent<PlayerMovement2>();
}
void Start() {
}
void Update()
{
tarRay.origin = transform.position;
tarRay.direction = transform.forward;
if (Input.GetButtonUp("Fire1"))
{
AnimationCancel();
}
if ( Input.GetButtonDown("Fire1"))
{
Animating();
}
}
void Attack ()
{
if (Physics.Raycast(tarRay, out tarHit, meleeRange))
{
var knockBackDirect = tarRay.direction;
knockBackDirect = transform.TransformPoint(0, 0, 0);
enemyHealth = tarHit.collider.GetComponent <PlayerHealth>();
enemyKnockback = tarHit.collider.GetComponent<PlayerMovement2>();
enemyHealth.TakeDamage(attackDamage);
enemyKnockback.Knockback(knockBackDirect);
playerMove.Knockback(new Vector3(0, 2, -3));
}
}
void Animating ()
{
bool attacking = true;
anim.SetBool("IsAttacking", attacking);
}
void AnimationCancel()
{
bool attacking = false;
anim.SetBool("IsAttacking", attacking);
}
}
I tried using Transformpoint to get a global Vector from my raycast as it would always be pointing away from the attacking player. This was a test and as a result my characters fly back really far, it’s hard to tell which direction they fly but I don’t think it worked. I’m pretty sure I’m going about this the wrong way
Here is my movement script where I define the Knockback function
using System;
using UnityEngine;
public class PlayerMovement2 : MonoBehaviour
{
public float p_Speed = 0.6f;
private float p_TurnSpeed = 180f;
private string p_MovementAxisName;
private string p_TurnAxisName;
private Rigidbody p_Rigidbody;
private float p_MovementInputValue;
private float p_TurnInputValue;
public Vector3 p_Knock;
Animator anim;
private void Awake()
{
p_Rigidbody = GetComponent<Rigidbody>();
anim = GetComponent<Animator>();
}
private void OnEnable ()
{
p_Rigidbody.isKinematic = false;
p_MovementInputValue = 0f;
p_TurnInputValue = 0f;
}
private void Start ()
{
p_MovementAxisName = "Vertical";
p_TurnAxisName = "Horizontal";
}
private void Update ()
{
p_MovementInputValue = Input.GetAxis(p_MovementAxisName);
p_TurnInputValue = Input.GetAxis(p_TurnAxisName);
}
private void FixedUpdate ()
{
Move();
Turn();
Animating();
}
private void Move ()
{
Vector3 movement = transform.forward * p_MovementInputValue * p_Speed * Time.deltaTime;
p_Rigidbody.MovePosition(p_Rigidbody.position + movement);
}
public void Knockback(Vector3 p_Knock)
{
p_Rigidbody.velocity = p_Knock;
p_Rigidbody.freezeRotation = true ;
}
private void Turn()
{
float turn = p_TurnInputValue * p_TurnSpeed * Time.deltaTime;
Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);
p_Rigidbody.MoveRotation(p_Rigidbody.rotation * turnRotation);
}
void Animating ()
{
bool walking = (p_MovementInputValue != 0f);
anim.SetBool("IsWalking", walking);
}
}
So, best way to do this?