敌人没有向玩家射击。仅检测玩家何时在左侧。敌人需要向玩家射击
Posted
技术标签:
【中文标题】敌人没有向玩家射击。仅检测玩家何时在左侧。敌人需要向玩家射击【英文标题】:Enemy not shooting at player. only detects when player is on left. Enemy needs to shoot at player 【发布时间】:2021-04-11 03:01:16 【问题描述】:到目前为止,我的敌人仅在玩家位于玩家左侧时才开枪,但如果敌人从左到右巡逻,则意味着当它从右到左移动且玩家仍在左侧时,它会向与玩家相反的方向射击代码工作正常。如果玩家在右边,而敌人从右往左走,它就不会射击,这很好,因为玩家在敌人身后。
如何让敌人只在玩家在前面时才射击,尤其是在开始时? 有什么办法可以简化这个吗?
这是我的代码
巡逻代码:
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;
*/
【问题讨论】:
【参考方案1】:您最好选择一个更简单的选项,该选项不需要那么多繁琐的代码,并且可以重复使用和更改每个预制件。
我会在 Enemy
预制件的前面放置一个碰撞器,并在 OnTriggerStay2D
方法中运行一个脚本来运行您的拍摄代码。
这样,您可以控制敌人的“视距”,而无需更改和重新编译任何代码,这也意味着您可以通过增加尺寸来拥有不同的敌人,它们的视锥更短或更大对撞机。
也只是几个指针:
您应该避免使用GameObject.Find("Enemy")
,除非您只打算在场景中使用一个名为Enemy
的游戏对象,因为它会选择找到的第一个。
相反,更好的选择是简单地将ShootPlayer
脚本放在你的敌人游戏对象上,并通过gameObject
引用它
您可能希望避免使用LayerMask.GetMask
,因为这可能是一项昂贵的操作,并且还会将您的代码与编辑器中的掩码紧密耦合。相反,如果您在该类上定义公共 LayerMask layerMask
字段,您将能够改为通过编辑器选择地面遮罩(以及任何其他应打磨的遮罩),并且遮罩名称的更改不会破坏你的代码。
【讨论】:
以上是关于敌人没有向玩家射击。仅检测玩家何时在左侧。敌人需要向玩家射击的主要内容,如果未能解决你的问题,请参考以下文章