Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Enemy detect and shoot in player direction when player is in front of it

Discussion in '2D' started by WhatIsInAName, Jan 5, 2021.

  1. WhatIsInAName

    WhatIsInAName

    Joined:
    Nov 15, 2020
    Posts:
    2
    So far my enemy only shoots when player is to the left of the player but if enemy is patrolling from left to right it means it shoots in opposite direction to player when it moves from right to left and player is still on the left code works fine. if player is to the right and enemy is going right to left it doesn't shoot which is fine since player is behind enemy.

    How do I get enemy to shoot only when player is in front especially at the start.

    Here are my codes

    Shooting player

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Threading;
    4. using System.Threading.Tasks;
    5. using UnityEngine;
    6.  
    7. public class ShootingPlayer : MonoBehaviour
    8. {
    9.  
    10.     //Cached component references
    11.     Animator enemyAnimator;
    12.  
    13.     //State
    14.     [SerializeField] GameObject enemy;
    15.     [SerializeField] GameObject fireBall;
    16.     [SerializeField] Transform shotSpawnPoint;
    17.  
    18.     [SerializeField] float timeBetweenShots ;
    19.     [SerializeField] float attackAnimationDuration;
    20.  
    21.     [SerializeField] float playerRange ;
    22.     [SerializeField] Transform player;
    23.  
    24.     private float nextShotTime;
    25.     private float endAttackAnimationTime;
    26.  
    27.     private void Awake()
    28.     {
    29.         enemy = GameObject.Find("Enemy");
    30.         enemyAnimator = enemy.GetComponent<Animator>();
    31.     }
    32.  
    33.     private void Start()
    34.     {
    35.         player = GameObject.FindGameObjectWithTag("Player").transform;
    36.     }
    37.  
    38.     // Update is called once per frame
    39.     void Update()
    40.     {
    41.         // draws line to detect player at a distance at the start and end of givem range, in this case behind and ahead of enemy
    42.         Debug.DrawLine( new Vector3(transform.position.x + playerRange, transform.position.y, transform.position.z), new Vector3(transform.position.x - playerRange, transform.position.y, transform.position.z));
    43.  
    44.        
    45.         if (player != null)
    46.         {
    47.             ShootAtPlayer();
    48.         }
    49.  
    50.      
    51.         if (enemyAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attacking") && Time.time > endAttackAnimationTime)
    52.         {
    53.             enemyAnimator.SetBool("Attacking", false);
    54.         }
    55.     }
    56.  
    57.     public void ShootAtPlayer()
    58.     {
    59.  
    60.         if (transform.localScale.x > 0 && player.transform.position.x < transform.position.x && player.transform.position.x > transform.position.x - playerRange && Time.time > nextShotTime)
    61.         {
    62.             Debug.Log("fireball going right");
    63.             Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
    64.             enemyAnimator.SetBool("Attacking", true);
    65.             nextShotTime = Time.time + timeBetweenShots;
    66.             endAttackAnimationTime = Time.time + attackAnimationDuration;
    67.         }
    68.  
    69.         // somehow never enters this loop
    70.  
    71.         if (transform.localScale.x < 0 && player.transform.position.x > transform.position.x && player.transform.position.x < transform.position.x + playerRange && Time.time > nextShotTime)
    72.         {
    73.             Debug.Log("fireball going left");
    74.             Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
    75.             enemyAnimator.SetBool("Attacking", true);
    76.             nextShotTime = Time.time + timeBetweenShots;
    77.             endAttackAnimationTime = Time.time + attackAnimationDuration;
    78.         }
    79.  
    80.         /* Continuous attacking
    81.  
    82.        if (Time.time > nextShotTime)
    83.        {
    84.            Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
    85.            enemyAnimator.SetBool("Attacking", true);
    86.            nextShotTime = Time.time + timeBetweenShots;
    87.            endAttackAnimationTime = Time.time + attackAnimationDuration;
    88.        }
    89.        */
    90.  
    91.  
    92.     }
    93. }
    94.  

    Fireball

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Fireball : MonoBehaviour
    6. {
    7.     public float speed;
    8.     public int damage;
    9.     public float lifeTime;
    10.     private GameObject player;
    11.  
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.        
    16.         //delay , basically to define, after how many seconds would we like to destroy game object
    17.         Destroy(gameObject, lifeTime);
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         transform.Translate(Vector2.left * speed * Time.deltaTime);
    24.     }
    25.  
    26.     private void OnTriggerEnter2D(Collider2D collision)
    27.     {
    28.         if (collision.tag == "Player")
    29.         {
    30.             collision.GetComponent<Player>().TakeDamage(damage);
    31.         }
    32.         Destroy(gameObject);
    33.     }
    34. }
    35.  

    patrol

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Patrol : MonoBehaviour
    6. {
    7.     public float speed;
    8.     public float distance;
    9.    
    10.  
    11.     private bool movingRight = true;
    12.  
    13.     public Transform groundDetection;
    14.    
    15.  
    16.     private void Update()
    17.     {
    18.         transform.Translate(Vector2.right * speed * Time.deltaTime);
    19.         int layer_mask = LayerMask.GetMask("Ground");
    20.      
    21.         RaycastHit2D groundinfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance, layer_mask); //origin, direction, distance
    22.      
    23.  
    24.         if (groundinfo.collider == false)
    25.         {
    26.             if(movingRight == true)
    27.             {
    28.                 transform.eulerAngles = new Vector3(0, -180, 0); //turn 180 degrees
    29.                 movingRight = false;
    30.             }
    31.             else
    32.             {
    33.                 transform.eulerAngles = new Vector3(0, 0, 0);
    34.                 movingRight = true;
    35.             }
    36.         }
    37.     }
    38.  
    39.  
    40. }
     
  2. Cornysam

    Cornysam

    Joined:
    Feb 8, 2018
    Posts:
    1,343
    You need to make it so the enemy only shoots when the player is in the raycast. When the enemy turns or "flips", the raycast should still face the same direction as the enemy.

    As for the projectile, you are using Vector2.left so it will always shoot left, even if you fix your raycast issue. Try using Vector2.forward or something like that.

    This is something i used in the past for a projectile that takes the player's X and Y position (aka it can shoot in different angles, not just horizontally.

    moveDirection = (target.transform.position - transform.position).normalized* moveSpeed;
    rb.velocity = new Vector2(moveDirection.x, moveDirection.y);
     
  3. WhatIsInAName

    WhatIsInAName

    Joined:
    Nov 15, 2020
    Posts:
    2
    I'm not terribly familiar with Raycasts could you please tell me what I should change for that to occur the way you mentioned. I'm an absolute beginner.

    as for the target position.. I'd need to take in the player as a transform and for some reason unity isn't letting me since the fireball script is on the prefab. which isn't actually in the scene. would you know what I could do as a workaround or if I'm calling the player wrong ?
     
  4. Cornysam

    Cornysam

    Joined:
    Feb 8, 2018
    Posts:
    1,343
    Try this quick video for raycasts. You actually already use one in your Patrol script on line 21. Basically, it shoots a ray out that records collisions. You can determine what collisions to detect, how long the ray goes and more. You can also use the Debug.DrawRay() function to show the ray while testing.

    https://docs.unity3d.com/ScriptReference/Debug.DrawRay.html

    You can grab the player's position when the fireball is instantiated.

    Code (CSharp):
    1.  
    2.     Player target;
    3.     Vector2 moveDirection;
    4.  
    5.  
    6.     void Awake()
    7.     {
    8.         rb = GetComponent<Rigidbody2D>();
    9.         target = FindObjectOfType<Player>();
    10.     }
    11.     // Use this for initialization
    12.     void Start ()
    13.     {    
    14.         moveDirection = (target.transform.position - transform.position).normalized* moveSpeed;
    15.         rb.velocity = new Vector2(moveDirection.x, moveDirection.y);
    16.     }