'trying to make an enemy shoot a projectile at the player when the player enters the enemys range
for some reason the projectile is fired but only when the enemy comes into contact with the player and very slowly for some reason. below is my code.
(there is a separate script on my projectile but that only deals with damage on the player)
public class flyingEnemy : MonoBehaviour {
public int maxHealth = 40;
Rigidbody2D rb2d;
public float speed;
public float attackRange;
private float lastAttackTime;
public float attackDelay;
public Transform target;
public float chaseRange;
public GameObject projectile;
public float bulletForce;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float distanceToTarget = Vector3.Distance(transform.position, target.position);
if(distanceToTarget < chaseRange)
{
//start chasing player
Vector3 targetDir = target.position - transform.position;
float angle = Mathf.Atan2(targetDir.y, targetDir.x) * Mathf.Rad2Deg - 90f;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, q, 180);
transform.Translate(Vector3.up * Time.deltaTime * speed);
}
if(distanceToTarget < attackRange)
{
//check to see if its time to attack again
if (Time.time > lastAttackTime + attackDelay)
{
//do we have lineofsight?
RaycastHit2D Hit = Physics2D.Raycast(transform.position, transform.up,attackRange);
//what did the raycast hit?
if (Hit.transform == target)
{
GameObject newBullet = Instantiate(projectile, transform.position, transform.rotation);
newBullet.GetComponent<Rigidbody2D>().AddRelativeForce(new Vector2(0f, bulletForce));
lastAttackTime = Time.time;
}
}
}
}
Solution 1:[1]
I modified your code and it seems to work now. I added a 'Player' layer to the player gameobject, then rewrote your script to the following:
using UnityEngine;
public class Enemy : MonoBehaviour
{
public int maxHealth = 40;
public float speed;
public float attackRange;
public float attackDelay;
public float chaseRange;
public float bulletForce;
private float lastAttackTime;
private float distanceToTarget;
public Transform target;
public GameObject projectile;
private Rigidbody2D rb2d;
private void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
if (distanceToTarget < chaseRange)
{
Chase(target.position);
}
else
{
rb2d.velocity = Vector2.zero;
}
}
private void Update()
{
distanceToTarget = Vector3.Distance(transform.position, target.position);
if (distanceToTarget < attackRange)
{
if (Time.time > lastAttackTime + attackDelay)
{
RaycastHit2D Hit = Physics2D.Raycast(transform.position, transform.up, attackRange, 1 << LayerMask.NameToLayer("Player"));
if (Hit)
{
Fire();
lastAttackTime = Time.time;
}
}
}
}
private void Chase(Vector3 target)
{
Vector3 targetDir = target - transform.position;
float angle = Mathf.Atan2(targetDir.y, targetDir.x) * Mathf.Rad2Deg - 90f;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, q, 180);
rb2d.velocity = targetDir.normalized * speed;
}
private void Fire()
{
GameObject newBullet = Instantiate(projectile, transform.position, transform.rotation);
newBullet.GetComponent<Rigidbody2D>().AddForce(transform.up * bulletForce, ForceMode2D.Impulse);
}
}
First, if you have a rigidbody, use that instead of Transform.Translate. Second, make sure your raycast only applies to the Player layer. Third, rather than
AddRelativeForce(new Vector2(0f, bulletForce));
use
AddForce(transform.up * bulletForce, ForceMode2D.Impulse);
Fourth, play around with the serialized values until you get the result you want. What I did was lower the enemy's speed and increase the bullet force. Let me know if you have any questions.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |