实例化敌人在其后生成的每个敌人输出双倍伤害

我正在制作一个FPS生存游戏。我编写了一个GameManager脚本来处理游戏中的敌人生成部分。我的EnemyAttack脚本负责敌人的攻击。问题是,当第一个敌人生成时,我只受到1点伤害(如AttackDamage中设置的),但当第二个敌人生成时,即使我只进入了一个敌人的攻击范围,我也会受到2点伤害(AttackDamage * 2)。以下是我所有的敌人脚本:

EnemyAttack.cs

   using UnityEngine;   using UnityEngine.UI;   using System.Collections;  public class EnemyAttack : MonoBehaviour  {public float AttackDamage = 1.0f;public float AttackSpeed = 1.0f;void Start() {    StartCoroutine(Attack());}IEnumerator Attack() {    while (true)    {        while (PlayerMovement.isEnemyAttacking == true) {            EnemyAttacking();            yield return new WaitForSeconds(AttackSpeed);        }        yield return 0;    }}public void EnemyAttacking() {    Debug.Log("Enemy Attacking!");    PlayerHealth.Health -= AttackDamage;    GameObject.FindGameObjectWithTag("HealthPoints").GetComponent<Text>().text = "HEALTH: " + PlayerHealth.Health;} }

EnemyAI.cs

   using UnityEngine;      using System.Collections;        public class EnemyAI : MonoBehaviour {public Transform TriggerBox;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update(){    if (EnemySight.inSight == true)    {        NavMeshAgent agent = GetComponent<NavMeshAgent>();        agent.destination = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>().position;    }     }    }

EnemySight.cs

     using UnityEngine;         using System.Collections;      public class EnemySight : MonoBehaviour {public static bool inSight = false;// Use this for initializationvoid Start(){}// Update is called once per framevoid Update(){}void OnTriggerEnter(Collider other){    if (other.gameObject.tag == "Player")    {        inSight = true;    }}void OnTriggerExit(Collider other) {    if (other.gameObject.tag == "Player")    {        inSight = false;    }   }   }

以及PlayerHealth.cs

  using UnityEngine;  using UnityEngine.UI;       using System.Collections;    public class PlayerHealth : MonoBehaviour {public Transform Player;public static float Health = 100;public static float maxHealth = 100;// Use this for initializationvoid Start () {    GameObject.FindGameObjectWithTag("HealthPoints").GetComponent<Text>().text = "HEALTH: " + Health;}// Update is called once per framevoid Update () {    if (Health <= 0) {        Dead();    }}public static void Dead() {} }

回答:

你的脚本存在一些问题…

我认为你对静态变量的理解可能有误。

静态变量在类的所有实例之间共享其值

来源

public static bool inSight;

不应该使用静态变量。

PlayerMovement.isEnemyAttacking

这也不应该使用静态变量。

目前,一旦有一个敌人满足“攻击”条件,你就会设置和读取一个单一的静态变量,导致所有敌人开始攻击。你应该让你的变量属于每个敌人的实例,而不是将你的变量设为静态。

基本上,你只需要理解什么是静态变量。一旦你明白了,你就会明白为什么你的逻辑不工作。

编辑:解决方案

PlayerHealth脚本。将此脚本附加到场景中的玩家GameObject上。

using UnityEngine;using UnityEngine.UI;public class PlayerHealth : MonoBehaviour{    public static float Health;    public static float maxHealth = 100;    private Text healthText;    void Start()    {        healthText = GameObject.FindGameObjectWithTag("HealthPoints").GetComponent<Text>();        //在开始时使其满100%的健康值        Health = maxHealth;        RefreshHealthBar();    }    public void TakeDamage(float damage)    {        Health -= damage;        RefreshHealthBar();        if (Health <= 0)            Die();    }    public void Die()    {        Health = 0;        RefreshHealthBar();        //TODO: 你的代码    }    void RefreshHealthBar()    {        healthText.text = "HEALTH: " + Health;    }}

EnnemyAI脚本。将此脚本附加到你的敌人预制件上。

 using System.Collections;using UnityEngine;public class EnnemyAI : MonoBehaviour{    public float AttackDamage = 1.0f;    public float AttackSpeed = 1.0f;    public float AttackRange = 1.0f;    private bool isPlayerInSight;    private GameObject target;    private NavMeshAgent agent;    // Use this for initialization    void Start ()    {        target = GameObject.FindGameObjectWithTag("Player");        agent = GetComponent<NavMeshAgent>();        StartCoroutine(AttackLoop());    }    // Update is called once per frame    void Update ()    {        if (isPlayerInSight)        {            agent.destination = target.transform.position;        }    }    IEnumerator AttackLoop()    {        while (true)        {            //我不知道你的攻击逻辑,所以假设他们可以在1单位范围内攻击            while (Vector3.Distance(target.transform.position, this.transform.position) <= AttackRange)            {                Attack();                yield return new WaitForSeconds(AttackSpeed);            }            yield return 0;        }    }    void Attack()    {        target.GetComponent<PlayerHealth>().TakeDamage(AttackDamage);    }    void OnTriggerEnter(Collider other)    {        if (other.gameObject.tag == "Player")        {            isPlayerInSight = true;        }    }    void OnTriggerExit(Collider other)    {        if (other.gameObject.tag == "Player")        {            isPlayerInSight = false;        }    }}
  1. 为了性能原因,我将FindGameObjectWithTag从Update()循环中移出。
  2. 玩家不再监听攻击。相反,敌人会向玩家发送伤害。

这样我们就去掉了静态变量。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注