2017-08-28 85 views
1

我一直在使用C#与Unity进行RPG游戏,并且在执行任务系统时,特别是杀死一定数量的敌人时,我发现在场景中有3个敌人,并成为任务的目标:杀死3个敌人。如果我在激活任务之前杀死他们,并且后来激活任务不会给我奖励(在这种情况下是经验)。我怎么能告诉敌人,如果任务发现我已经杀死了必要的敌人以获得任务,同样给我奖励呢?如何在场景中实现“杀死”事件的意识


这里两个需要的脚本,我认为:

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

public class QuestObject : MonoBehaviour { 

    public int questNumber; 

    public QuestManager qManager; 

    public string startText; 
    public string endText; 

    public bool isItemQuest; 
    public string targetItem; 

    public bool isEnemyQuest; 
    public string targetEnemy; 
    public int enemiesToKill; 
    private int enemyKillCount; 

    private PlayerStats playerStats; 
    public int EXPToGive; 

    void Start() { 
     playerStats = FindObjectOfType <PlayerStats>(); 
    } 

    void Update() { 

     if (isItemQuest) { 

      if (qManager.itemCollected == targetItem) { 

       qManager.itemCollected = null; 
       EndQuest(); 
      } 
     } 


     if (isEnemyQuest) { 

      if (qManager.enemyKilled == targetEnemy) { 

       qManager.enemyKilled = null; 

       enemyKillCount++; 

      } 

      if (enemyKillCount >= enemiesToKill) { 

       EndQuest(); 

      } 
     } 
    } 

    public void StartQuest(){ 
     qManager.ShowQuestText (startText); 



    } 

    public void EndQuest(){ 
     qManager.ShowQuestText (endText); 
     playerStats.AddEXP (EXPToGive); 
     qManager.questCompleted [questNumber] = true; 
     gameObject.SetActive (false); 


    } 
} 

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

public class EnemyHealth : MonoBehaviour { 

    public int startingHealth;         
    public int currentHealth;         
    public GameObject damageBurst; 
    private PlayerStats playerStats; 
    public int EXPToGive; 

    public string enemyQuestName; 
    private QuestManager qManager; 




    void Start() 
    { 
     // Setting up the references. 
     //anim = GetComponent <Animator>(); 
     //enemyAudio = GetComponent <AudioSource>(); 
     //enemyMovement = GetComponent <EnemyMovement>(); 
     //enemyAttacking = GetComponentInChildren <EnemyAttack>(); 
     // Set the initial health of the player. 
     currentHealth = startingHealth; 
     playerStats = FindObjectOfType <PlayerStats>(); 
     qManager = FindObjectOfType <QuestManager>(); 
    } 



    void Update() 
    { 
     if (currentHealth <= 0) { 

      qManager.enemyKilled = enemyQuestName; 

      Destroy (gameObject); 
      playerStats.AddEXP (EXPToGive); 
     } 
    } 


    public void TakeDamage (int amountDamage) 
    { 
     // Reduce the current health by the damage amount. 
     currentHealth -= amountDamage; 
     Instantiate (damageBurst, transform.position, transform.rotation); 


    } 

    public void SetMaxHelth() { 
     currentHealth = startingHealth; 
    } 


} 

回答

3

一个阿布罗奇是创建某种类型的“WorldManager”,其对每一个已被杀害敌人的。当开始一个任务时,这个任务可以检查WorldManagers的杀戮数量并将其添加到自己的数量中。

public void StartQuest(){ 
     qManager.ShowQuestText (startText); 
     this.enemyKillCount += worldManager.GetKillCount(); 
    } 

在你的敌人职业中,你必须为你的worldManager添加杀戮。

void Update() 
    { 
     if (currentHealth <= 0) { 

      qManager.enemyKilled = enemyQuestName; 
      this.worldManager.AddKill(this) 
      Destroy (gameObject); 
      playerStats.AddEXP (EXPToGive); 
     } 
    } 

备选:

让您QManager知道每一个场景杀死。 您可以通过多种方式实现此目的。 其中之一是传递你的EnemyObject作为你的Qmanager的参考,并且与上面提供的“WorldManager”一样,或者当敌人被杀时使用消息传递并触发一条消息来瞄准QManager。

备选方案2: 当敌人被杀死并在QManager/WorldManager上订阅时投掷一个事件。这样你就可以在每场比赛中重复使用你的敌人。从我的角度来看,静态依赖是邪恶的,但是互联网上有许多讨论和SO以及无处不在。

+0

好的谢谢,但我不明白AddKill(this)在哪里发送这些信息,我在哪里添加AddKill。和GetKillCount()?而且我不知道如何去做敌人台你能帮我吗?我有两个分离类型的敌人哥布林和史莱姆。 – adrinator8

1

你可以采取几种方法。最直接的是使用静态。

静态的目的是为变量/方法属于类而不是类的实例。

就你而言,你希望每个敌人都有自己的健康,这不能是静态的。 你想要统计场景中有多少实例。所以静态很好。

public class Enemy:MonoBehaviour 
{ 
    private static int enemyCount = 0; 
    public static int EnemyCount {get{ return enemyCount;} } 
    public event Action<int> RaiseEnemyDeath; 
    public static void ResetEnemyCount(){ 
      enemyCount = 0; 
    } 

    private int health; 
    public void Damage(int damage) 
    { 
     CheckForDamage(); // here you check that damage is not neg or too big... 
     this.health -= damage; 
     if(this.health <= 0) 
     { 
      OnDeath(); 
     } 
    } 
    void OnActivate() 
    { 
     enemyCount++; 
     this.health = 20; 
    } 
    void OnDeath() 
    { 
     enemyCount--; 
     RaiseEnemyDeath(enemyCount); // Should check for nullity... 
    } 
} 

这个很简单。第一部分全部是静态的,与班级相关。第二部分与实例相关。如果你使用一群敌人,然后多次重复使用同一个实例,当你让敌人在场景中存活时(它可能已经在那里停留一段时间),就会调用OnActivate方法。然后当健康状况下降时,杀死敌人(那里没有所有必要的行动......)并触发事件。

使用公共静态属性,您可以知道GameManager的敌人数量是多少(敌人不应该影响游戏玩法,只会照顾敌人)。

public class GameManager:MonoBehaviour 
{ 
    void Start() 
    { 
     Enemy.RaiseEnemyDeath += Enemy_RaiseEnemyDeath; 
    } 
    void Enemy_RaiseEnemyDeath(int count) 
    { 
     if(count < 0){ // End of level } 
     // You can also access enemyCount 
     int count = Enemy.EnemyCount; 
    } 
} 

好点利用这个原理的是,敌人没有关于游戏管理的线索,可以在另一场比赛没有任何修改被重用。 GameManager是一个更高层次的实体并且知道它。

+0

我喜欢使用事件的方式,但如果你不使用静态的话,我更喜欢那个解决方案。但有一个好的解决方案。 –

+0

这里的静态实际上是合适的。敌人的数量与敌人级有关。你也可以通过一些更高层次的经理来实现。当您认为即使没有Enemy实例时仍然需要静态,您仍然可以检查EnemyCount的值。如果静态在这里是无效的,那么在一般编程中根本就没有理由。 – Everts