How can I move an object in the direction another object is facing.
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?
Answer by vintar · Dec 31, 2015 at 08:47 PM
Easiest way is to get the direction in which the attack happened and to do that you would say :
Vector3 direction = objectA.transform.position - objectB.transform.position;
Then pass "direction" to your knockback method.
Thanks, this has worked for me. But now I have a new problem, there's no lift to the knockbacks. I want the enemies to lift up off the ground when I attack. Is there away to add some Y axis to this?
$$anonymous$$y code now looks like this:
Attack Function:
if (Physics.Raycast(tarRay, out tarHit, meleeRange))
{
enemyHealth = tarHit.collider.GetComponent <PlayerHealth>();
enemyBody = tarHit.collider.GetComponent<Transform>();
enemy$$anonymous$$nockback = tarHit.collider.GetComponent<Player$$anonymous$$ovement2>();
Vector3 knockBackDirection = enemyBody.position - playerBody.position;
Vector3 knockBackHit = playerBody.position - enemyBody.position;
enemyHealth.TakeDamage(attackDamage);
enemy$$anonymous$$nockback.$$anonymous$$nockback(knockBackDirection,7);
player$$anonymous$$ove.$$anonymous$$nockback(knockBackHit,5);
}
$$anonymous$$nockback Function:
public void $$anonymous$$nockback(Vector3 p_$$anonymous$$nock, float p_Force )
{
var knockBack = p_$$anonymous$$nock * p_Force;
p_Rigidbody.velocity = knockBack;
p_Rigidbody.freezeRotation = true ;
}
Your answer
Follow this Question
Related Questions
Cant Get a Bullet to Shoot (C#) 2 Answers
Keep getting Error CS0131 1 Answer
How to get local angle of travel 0 Answers
c# jumping isn't consistent, please help 0 Answers
How does rigidbody velocity works? 1 Answer