Враг не стреляет в игрока. определяет только когда игрок слева. Враг должен стрелять в игрока

Пока мой враг стреляет только тогда, когда игрок находится слева от игрока, но если враг патрулирует слева направо, это означает, что он стреляет в противоположном направлении от игрока, когда он движется справа налево, а игрок все еще находится слева код работает нормально . если игрок находится справа, а противник идет справа налево, он не стреляет, что нормально, поскольку игрок находится позади врага.

Как заставить врага стрелять только тогда, когда игрок идет впереди, особенно на старте? Есть ли способ упростить это?

Вот мои коды

Код патруля:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Patrol : MonoBehaviour
{
   public float speed;
   public float distance;
   

   private bool movingRight = true;

   public Transform groundDetection;
   

   private void Update()
   {
       transform.Translate(Vector2.right * speed * Time.deltaTime);
       int layer_mask = LayerMask.GetMask("Ground");
      
       RaycastHit2D groundinfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance, layer_mask); //origin, direction, distance
      

       if (groundinfo.collider == false)
       {
           if(movingRight == true)
           {
               transform.eulerAngles = new Vector3(0, -180, 0); //turn 180 degrees
               movingRight = false;
           }
           else
           {
               transform.eulerAngles = new Vector3(0, 0, 0);
               movingRight = true;
           }
       }
   }


}

Код огненного шара (прикреплен к сборному объекту огненного шара)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Fireball : MonoBehaviour
{
   public float speed;
   public int damage;
   public float lifeTime;
   private GameObject player;

   // Start is called before the first frame update
   void Start()
   {
       
       //delay , basically to define, after how many seconds would we like to destroy game object
       Destroy(gameObject, lifeTime); 
   }

   // Update is called once per frame
   void Update()
   {
       transform.Translate(Vector2.left * speed * Time.deltaTime);
   }

   private void OnTriggerEnter2D(Collider2D collision)
   {
       if (collision.tag == "Player")
       {
           collision.GetComponent<Player>().TakeDamage(damage);
       }
       Destroy(gameObject);
   }
}

Скрипт стреляющего игрока:

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

public class ShootingPlayer : MonoBehaviour
{

   //Cached component references
   Animator enemyAnimator;

   //State
   [SerializeField] GameObject enemy;
   [SerializeField] GameObject fireBall;
   [SerializeField] Transform shotSpawnPoint;

   [SerializeField] float timeBetweenShots ;
   [SerializeField] float attackAnimationDuration;

   [SerializeField] float playerRange ;
   [SerializeField] Transform player;

   private float nextShotTime;
   private float endAttackAnimationTime;

   private void Awake()
   {
       enemy = GameObject.Find("Enemy");
       enemyAnimator = enemy.GetComponent<Animator>();
   }

   private void Start()
   {
       player = GameObject.FindGameObjectWithTag("Player").transform;
   }

   // Update is called once per frame
   void Update()
   {
       // draws line to detect player at a distance at the start and end of givem range, in this case behind and ahead of enemy
       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));

       
       if (player != null)
       {
           ShootAtPlayer();
       }

      
       if (enemyAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attacking") && Time.time > endAttackAnimationTime)
       {
           enemyAnimator.SetBool("Attacking", false);
       }
   }

   public void ShootAtPlayer()
   { 

       if (transform.localScale.x > 0 && player.transform.position.x < transform.position.x && player.transform.position.x > transform.position.x - playerRange && Time.time > nextShotTime)
       {
           Debug.Log("fireball going right");
           Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
           enemyAnimator.SetBool("Attacking", true);
           nextShotTime = Time.time + timeBetweenShots;
           endAttackAnimationTime = Time.time + attackAnimationDuration;
       }

       // somehow never enters this loop

       if (transform.localScale.x < 0 && player.transform.position.x > transform.position.x && player.transform.position.x < transform.position.x + playerRange && Time.time > nextShotTime)
       {
           Debug.Log("fireball going left");
           Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
           enemyAnimator.SetBool("Attacking", true);
           nextShotTime = Time.time + timeBetweenShots;
           endAttackAnimationTime = Time.time + attackAnimationDuration;
       }

       /* Continuous attacking

      if (Time.time > nextShotTime)
      {
          Instantiate(fireBall, shotSpawnPoint.position, shotSpawnPoint.rotation);
          enemyAnimator.SetBool("Attacking", true);
          nextShotTime = Time.time + timeBetweenShots;
          endAttackAnimationTime = Time.time + attackAnimationDuration;
      }
      */


   }
}


person Charlie TheIndieDev    schedule 05.01.2021    source источник


Ответы (1)


Вам может быть лучше выбрать более простой вариант, который не потребует столько сложного кода и может быть повторно использован и изменен для каждого префаба.

Я бы поместил коллайдер перед префабом Enemy и создал сценарий, который запускает ваш код съемки внутри метода OnTriggerStay2D.

Таким образом, вы можете контролировать расстояние обзора вашего врага без необходимости изменять и перекомпилировать какой-либо код, а также это означает, что у вас могут быть разные враги с более коротким или большим конусом обзора, просто увеличивая размер коллайдера.

Также всего пара указателей:

  • Вам следует избегать использования GameObject.Find("Enemy"), если только вы не планируете иметь в своей сцене только один игровой объект с названием Enemy, поскольку он выберет первый найденный.

    Вместо этого лучшим вариантом было бы просто разместить ShootPlayer скрипт на вашем вражеском игровом объекте и ссылаться на него через gameObject

  • Возможно, вы захотите избежать использования LayerMask.GetMask, поскольку это может быть дорогостоящая операция, а также тесно связывает ваш код с масками в редакторе. Вместо этого, если вы определите общедоступное поле LayerMask layerMask для этого класса, вы сможете выбрать маску заземления (а также любую другую маску, которая должна быть заземлена) через редактор, и изменение имени маски не нарушит вашу работу. код.

person Beardy    schedule 05.01.2021