Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Enemy AI Shooting At Player

Hi :)

So im making this 2d infinite runner game that has an enemy which shoots at player.

this is the code im using for the bullet:

public class EnemyBullet : MonoBehaviour

{

public float speed = 20f;

public int damage = 40;

public GameObject impactEffect;

private Vector3 target;

private Transform player;

private Vector3 bulletTrans;

private Rigidbody2D rb;


// Use this for initialization

void Start()

{

player = GameObject.FindGameObjectWithTag("Player").transform;

bulletTrans = new Vector3(transform.position.x, transform.position.y, transform.position.z);

rb = GetComponent<Rigidbody2D>();

target = new Vector3(player.position.x, player.position.y,player.position.z);


}


void OnTriggerEnter2D(Collider2D hitInfo)

{

PlayerStats playerhit = hitInfo.GetComponent<PlayerStats>();

if (playerhit != null)

{

playerhit.TakeDamage(damage);

DestoryBullet();

}

}


private void FixedUpdate()

{

rb.velocity = (target - bulletTrans).normalized * speed;


}

void DestoryBullet()

{

Instantiate(impactEffect, transform.position, transform.rotation);

Destroy(gameObject);

}

}

________________________________________________________________________

the problem that im having is that the speed of the bullet changes depending of the distance between the enemy and player.

i just want the bullet to go straight to the position where the player was in the time the bullet was instantiated.

Best Answer

  • ShahekGamesShahekGames Member
    Accepted Answer

    @Sl0th Hi i made some changes and its working fine now.

    i made a gun for enemy that rotates towards the player.

    here are 3 scripts i am using to make it happen for anyone having my problem:

    ** Enemy Script **

    ___________________________________________________

    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;


    public class Enemy : MonoBehaviour

    {

      public float speed;

      public float timeBTWShots;

      public float startTimeBTWShots;

      public int damage = 1;

      public GameObject deathEffect;

      public Transform barrel;

      public int health = 1;

      public Gun gun;

      void Start()

      {


      }


      // Update is called once per frame

      void FixedUpdate()

      {

        transform.Translate(Vector2.left * speed * Time.fixedDeltaTime);

        if (transform.position.x <= -6)

        {

          Destroy(gameObject);

        }


        if(timeBTWShots <= 0)

        {

          gun.Shoot();

          timeBTWShots = startTimeBTWShots;

        }

        else

        {

          timeBTWShots -= Time.fixedDeltaTime;

        }


      }



      public void TakeDamage(int damage)

      {

        health -= damage;


        if (health <= 0)

        {

          Die();

        }



      }


      void Die()

      {

        Instantiate(deathEffect, transform.position, Quaternion.identity);

        Destroy(gameObject);

      }


      private void OnTriggerEnter2D(Collider2D other)

      {

        if (other.CompareTag("Player"))

        {

          other.GetComponent<PlayerStats>().TakeDamage(damage);

          Instantiate(deathEffect, transform.position, Quaternion.identity);

          Destroy(gameObject);

        }

      }

    }

    __________________________________________________________

    ** Gun Script **

    __________________________________________________________

    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;


    public class Gun : MonoBehaviour

    {

      Transform playerT;

      public GameObject bullet;

      // Start is called before the first frame update

      void Start()

      {

        playerT = GameObject.FindGameObjectWithTag("Player").transform;

      }


      // Update is called once per frame

      void Update()

      {

        RotateTowards(playerT.position);

      }


      public void RotateTowards(Vector2 target)

      {

        float offset = 90f;

        Vector2 direction = target - (Vector2)transform.position;

        direction.Normalize();

        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;

        transform.rotation = Quaternion.Euler(Vector3.forward * (angle + offset));

      }


      public void Shoot()

      {

        Instantiate(bullet, transform.position, transform.rotation);

      }

    }

    _____________________________________________________________

    ** Enemy Bullet Script **

    _____________________________________________________________

    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;


    public class EnemyBullet : MonoBehaviour

    {

    public float speed = 20f;

    public int damage = 40;

    public GameObject impactEffect;

    private Vector2 target;

    private Transform player;

    private Vector2 bulletTrans;

    private Rigidbody2D rb;


    // Use this for initialization

    void Start()

    {

    player = GameObject.FindGameObjectWithTag("Player").transform;

    bulletTrans = new Vector2(transform.position.x, transform.position.y);

    rb = GetComponent<Rigidbody2D>();

    target = new Vector2(player.position.x, player.position.y);


    }


    void OnTriggerEnter2D(Collider2D hitInfo)

    {

    PlayerStats playerhit = hitInfo.GetComponent<PlayerStats>();

    if (playerhit != null)

    {

    playerhit.TakeDamage(damage);

    DestoryBullet();

    }

    }


    private void FixedUpdate()

    {

    rb.velocity = -(transform.up * speed);


    }

    void DestoryBullet()

    {

    Instantiate(impactEffect, transform.position, transform.rotation);

    Destroy(gameObject);

    }

    }

    ___________________________________________________________

    Thank you @Sl0th For Your Time <3

Answers

  • Hey, can you please describe how the speed changes? Does it get slower or faster as it gets closer?

    Also, remember to multiply the velocity with time.FixedDeltaTime, to make it the same across frame rates (this could be the source of the problem, in case the game comes under serious pressure while shooting for some reason).

    Also, I believe Vector3 is value type, so you should be able to say target = player.position etc. without problems.

    Finally, why use Vector3 at all in a 2D game?

    Hope the advice helps!

  • @Sl0th it moves faster when the distance is more. i changed it to Vector2 now. and when i multiplied it with time.fixedDeltaTime it doesnt shoot at the player direction anymore. and i did put target = player.position before but then the bullet will follow the player instead of going in the direction of player and continue moving.

    this is my code now:

    public class EnemyBullet : MonoBehaviour

    {

    public float speed = 20f;

    public int damage = 40;

    public GameObject impactEffect;

    private Vector2 target;

    private Transform player;

    private Vector2 bulletTrans;

    private Rigidbody2D rb;


    // Use this for initialization

    void Start()

    {

    player = GameObject.FindGameObjectWithTag("Player").transform;

    bulletTrans = new Vector2(transform.position.x, transform.position.y);

    rb = GetComponent<Rigidbody2D>();

    target = new Vector2(player.position.x, player.position.y);


    }


    void OnTriggerEnter2D(Collider2D hitInfo)

    {

    PlayerStats playerhit = hitInfo.GetComponent<PlayerStats>();

    if (playerhit != null)

    {

    playerhit.TakeDamage(damage);

    DestoryBullet();

    }

    }


    private void FixedUpdate()

    {

    rb.velocity = (target - bulletTrans).normalized * speed * Time.fixedDeltaTime;


    }

    void DestoryBullet()

    {

    Instantiate(impactEffect, transform.position, transform.rotation);

    Destroy(gameObject);

    }

    }

    ___________________________

    im just having problems in movement part. i want the bullet to move towards the player's position and continue moving.

  • Hmm, that's odd... By the way, the fixedDeltaTime was my bad, it shouldn't be there. Sorry about that. It shouldn't have went in another direction because of that, though. It should just have moved slower. Are there any other forces acting on the bullet? What happens if you don't give it any velocity at all?

    Also, what happens if you just calculate the velocity once and store it in a variable and then just apply the value of that variable?

  • @Sl0th nope no other forces. it just gets instantiated by enemy and moves towards the players position when it was instantiated.

    i just want the bullet to move towards a position and the continue moving.

    how can i do that? help me :(

  • I just set up a project to test the code myself, and I face no problems. The only explanation I can think of is that you have forgotten to turn off gravity on the RigidBody or that something else is accessing the bullet's rigidbody or EnemyBullet script.

  • @Sl0th am i using a right code for this purpose? i just want a simple bullet script.

    nothing else is accessing the bullet's rigidbody or this script. and there is no gravity in the whole scene.

    how will you do prefab based shooting for the enemies? is there a code or tutorial for that?

    idk why my code isnt working properly.

    it shoots normal when the player is near the center but it shoots faster and less accurate when the player is far away from the enemy and near the screen edges.

    the enemy moves to the left only and it instantiates a bullet with this scripts attached on it.

    what part is wrong?

    i would be grateful if you provide me a tutorial for all the shooting bullet things.

    i dont know how to design a shotgun or a wave of bullets or ...

    can you help me?

    Thanks!

  • To be honest, I'd write it quite differently. I don't know about a tutorial, but I can make you an example at some point later. I'll need to know a few things first, though.

    Can you show me your enemy script, if there is one?

    Do you know what inheritance is? Do you know what an interface is?

  • @Sl0th

    Hi this is the Enemy Script:

    using System.Collections;

    using System.Collections.Generic;

    using UnityEngine;


    public class Enemy : MonoBehaviour

    {

      public float speed;

      public float timeBTWShots;

      public float startTimeBTWShots;

      public GameObject bullet;

      public int damage = 1;

      public GameObject deathEffect;

      public Transform barrel;

      public int health = 1;

      void Start()

      {

        

      }


      // Update is called once per frame

      void FixedUpdate()

      {

        transform.Translate(Vector2.left * speed * Time.fixedDeltaTime);

        if (transform.position.x <= -6)

        {

          Destroy(gameObject);

        }


        if(timeBTWShots <= 0)

        {

          Instantiate(bullet, barrel.position, Quaternion.identity);

          timeBTWShots = startTimeBTWShots;

        }

        else

        {

          timeBTWShots -= Time.fixedDeltaTime;

        }

      }


      public void TakeDamage(int damage)

      {

        health -= damage;


        if (health <= 0)

        {

          Die();

        }



      }


      void Die()

      {

        Instantiate(deathEffect, transform.position, Quaternion.identity);

        Destroy(gameObject);

      }


      private void OnTriggerEnter2D(Collider2D other)

      {

        if (other.CompareTag("Player"))

        {

          other.GetComponent<PlayerStats>().TakeDamage(damage);

          Instantiate(deathEffect, transform.position, Quaternion.identity);

          Destroy(gameObject);

        }

      }

    }

    ______________________________

    and no i dont know what are they. im just doing game dev for fun and hobby and maybe make some money from it.

    and i have one more question.

    the Scriptable Objects i know we can use them to store data in them. if i use them for prefabs that have scripts with values for variables which are same between several prefabs will it make performance better?

    Thanks!!

  • Alright, I'll take a look at it later.

    I'm not sure I understand your question. They can be used to take less space, but I don't think they necessarily can increase performance. I haven't tried them out much, though. But if you need 10 weapons that have different stats, for example, it's way better to make a prefab that has a script that takes a scriptable object, and then have 10 scriptable objects with the stats, than it is to make 10 prefabs.

Sign In or Register to comment.