【问题标题】:Unity-Issue with spawning enemies after first wave is defeated第一波被击败后产生敌人的团结问题
【发布时间】:2016-11-06 19:45:48
【问题描述】:

我正在开发一个包含三种不同类型敌人的统一项目。现在,我知道当游戏开始时,三个敌人中的一个都会出现。到目前为止,一切都很好。问题是,当我杀死一个敌人时,我希望这种类型的敌人一遍又一遍地生成。所以基本上,游戏从每个敌人中的一个开始,没有其他敌人出现。当我杀死其中一种类型时,那种类型会一遍又一遍地出现,直到他们可能会杀死我。这是我的代码:

    public bool waveOne = true;
    public float subTime = .5f; //Lab 11 work

    #endregion Member Variables

    #region Member Functions

    void Start ()
    {
    if (waveOne == true) {
            Invoke ("Spawn", spawnTime);
        } 
        else {
            // Call the Spawn function after a delay of the spawnTime and then continue to call after the same amount of time.
            InvokeRepeating ("Spawn", spawnTime, spawnTime);
        }
    }

上面的函数是生成每种类型的一种。

我尝试创建这个函数来调用重复的敌人:

    public void callEnemies()
    {
        waveOne = false;
        InvokeRepeating ("Spawn", spawnTime, spawnTime);

    }

我会在我的死亡函数下调用我的敌人健康.cs 中的 callEnemies。

        public void Death ()
    {
        // The enemy is dead.
        isDead = true;

        // Turn the collider into a trigger so shots can pass through it.
        capsuleCollider.isTrigger = true;
        EnemyManager.Instance.callEnemies();

        // Tell the animator that the enemy is dead.
        anim.SetTrigger ("Dead");

        // Change the audio clip of the audio source to the death clip and play it (this will stop the hurt clip playing).
        enemyAudio.clip = deathClip;
        enemyAudio.Play ();


        #region Lab10 Addition

        // Kill the Enemy (remove from EnemyList)
        // Get the game object associated with "this" EneymHealth script
        // Then get the InstanceID of that game object.
        // That is the game object that needs to be killed.
        EnemyManager.Instance.Kill(this.gameObject.GetInstanceID());

        #endregion // Lab10 Addition

    }

所以现在,我的三个敌人中只有一个倾泻而出。但其他两个没有。任何帮助都会很棒!

使用 System.Collections.Generic; 使用 UnityEngine;

公共类 EnemyManager : MonoBehaviour { #region 成员变量

    #region LAB10 Addition

    public static EnemyManager Instance
    {
        get { return EnemyManager._Instance; }
    }
    private static EnemyManager _Instance = null;

    public EnemyManager()
    {
        if (EnemyManager._Instance == null) EnemyManager._Instance = this;
    }

    public Dictionary<int, Object> EnemyList = new Dictionary<int, Object>();

    #endregion // LAB10 Addition


    public PlayerHealth playerHealth;       // Reference to the player's heatlh.
    public GameObject enemy;                // The enemy prefab to be spawned.
    public float spawnTime = 3f;            // How long between each spawn.
    public Transform[] spawnPoints;         // An array of the spawn points this enemy can spawn from.
    public bool waveOne = true;
    public float subTime = .5f; //Lab 11 work

    #endregion Member Variables

    #region Member Functions

    void Start ()
    {
    if (waveOne == true) {
            Invoke ("Spawn", spawnTime);
        } 
        else {
            // Call the Spawn function after a delay of the spawnTime and then continue to call after the same amount of time.
            InvokeRepeating ("Spawn", spawnTime, spawnTime);
        }
    }


    void Spawn ()
    {
        // If the player has no health left...
        if(playerHealth.currentHealth <= 0f)
        {
            // ... exit the function.
            return;
        }

        // Find a random index between zero and one less than the number of spawn points.
        int spawnPointIndex = Random.Range (0, spawnPoints.Length);

        #region LAB10 Addition

        // Create an instance of the enemy prefab at the randomly selected spawn point's position and rotation.
        // Original Code (next line) did not capture the resulting object.
        // Instantiate(enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
        Object o = Instantiate(enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
        EnemyManager.Instance.EnemyList.Add(o.GetInstanceID(), o);

        #endregion // LAB10 Addition

    #region Lab 11

    ((GameObject)o).GetComponent<EnemyHealth>().EnemyHealthHandler += ScoreManager.EnemyHealthEvent;


    #endregion

    }

    #region Lab10 Addition

    public void Kill(int InstanceID)
    {
        if (EnemyManager.Instance.EnemyList.ContainsKey(InstanceID))
            EnemyManager.Instance.EnemyList.Remove(InstanceID);

    //Lab 11 notes
    //bool IsAlive = (playerHealth.currentHealth <= 0f) ? true : false;

    }

    public void DeathToAll()
    {
        Dictionary<int, Object> TempEnemyList = new Dictionary<int, Object>(EnemyManager.Instance.EnemyList);
        foreach (KeyValuePair<int, Object> kvp in TempEnemyList)
        {
            // kvp.Key;   // = InstanceID
            // kvp.Value; // = GameObject

            GameObject go = (GameObject)kvp.Value;
            go.GetComponent<EnemyHealth>().Death();
        }

    }

    #endregion // Lab10 Addition

    public void callEnemies()
    {
        waveOne = false;
        InvokeRepeating ("Spawn", spawnTime, spawnTime);

    }

    #endregion Member Functions
}

【问题讨论】:

  • 您能否包含实际生成敌人的代码?
  • @Abion47-我在最近的编辑中包含了完整的代码。
  • 当你生成一个敌人时,你会在 enemy 对象中生成一个预制件的实例,但是我在你的代码中没有看到将 enemy 重新分配给其他任何东西的任何地方。这就是为什么你只生成一种类型的敌人,因为你没有告诉你的游戏生成其他任何东西。
  • 你知道如何解决这个问题吗?我刚开始使用 Unity。

标签: c# unity3d unity5


【解决方案1】:

如果我正确理解你的意图,你的陷阱就在你的“Spawn”方法中

void Spawn ()
    {
        if(playerHealth.currentHealth <= 0f)
        {
            return;
        }
        int spawnPointIndex = Random.Range (0, spawnPoints.Length);
        Object o = Instantiate(enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation); // only one
        EnemyManager.Instance.EnemyList.Add(o.GetInstanceID(), o);
       ((GameObject)o).GetComponent<EnemyHealth>().EnemyHealthHandler += ScoreManager.EnemyHealthEvent;
    }

您仅从加载到一个游戏对象的预制件中实例化一个敌人。我们没有足够的代码来编写完整的解决方案,但您似乎希望实例化所有三个并跟踪哪种类型被杀死以产生更多该类型。

编辑: 阅读您的评论后,我明白为什么它会卡在一个敌人身上。 看看单例:

public static EnemyManager Instance
    {
        get { return EnemyManager._Instance; }
    }
    private static EnemyManager _Instance = null;

    public EnemyManager()
    {
        if (EnemyManager._Instance == null) EnemyManager._Instance = this;
    }

当你创建第一个敌人时,_instance 被设置为“this”。当你尝试制造第二个敌人时,if 语句为假,并且敌人的类型仍然是第一个。

脚本的所有实例的静态 _instance 都是相同的。

【讨论】:

  • 感谢您的回复。然而,我们团结一致地把剧本附加到他们三个敌人身上。所以基本上每个敌人都有一个“脚本”。不知道这是否有帮助,但谢谢你。
  • @MikeCuddy 你不应该完全由不同的敌人类型来处理产卵行为,因为他们无法相互交流并决定接下来应该产卵。您应该有一个 SpawnManager 脚本来独立处理产卵。
  • @MikeCuddy 真的。我完善了我的答案。 Abion47 的方法暗示了正确的设计模式。
  • 对于单例模式,最好在静态构造函数中实例化单例。
  • 感谢您的帮助,我将继续努力,看看我能找到什么!
猜你喜欢
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
相关资源
最近更新 更多