2017-08-28 8 views
1

私はUnityでRPGゲームをC#でやっていますが、特定の数の敵を殺すクエストシステムを実行すると、シーンに3人の敵を持っていて、クエストの対象になっている:3人の敵を殺す。クエストをアクティブにして後でアクティブにする前にそれらを殺すと、報酬(この場合は経験)が得られません。どのように私は敵を告げることができ、クエストが私にすでに必要な敵を殺してクエストを受けることが検出された場合、それと同等の報酬を私に与えることができますか?シーン内の「kill」イベントの認識を達成する方法


は、ここでは、2つの必要なスクリプトは、私は思う:

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

一つAproachが殺害されたすべての敵を数える "WorldManager" のいくつかのタイプを作成することです。そして、クエストを開始するとき、このクエストはワールドマネージャーが数を殺してそれを自分の数に加えることをチェックすることができます。

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は、あらゆるシーンで殺すのに注意してください。 これはさまざまな方法で実現できます。 それらのうちの1人はあなたのEnemyObjectをあなたのQmanagerのリファレンスとして渡しており、上記で提供されている "WorldManager"と同じことをやっているか、Messagingを使って敵が殺されたときにQManagerをターゲットにしたメッセージを発射します。

代替2: 敵が殺され、QManager/WorldManagerで購読したときにイベントを投げる。これにより、すべてのゲームで敵クラスを再利用できます。私の視点から見ると、静的な依存関係は悪いですが、それについてインターネット上には多くの議論があります。

+0

ありがとうございますが、私はAddKill(this)がこの情報をどこに送信しているのか分からず、AddKillを置く場所があります。そしてGetKillCount()?そして私は敵のカウンターを行う方法を知らない私を助けることができますか?私は2つのタイプの敵であるゴブリンとスライムを持っています。 – adrinator8

1

いくつかの方法があります。最も単純なのは、staticを使用することです。

staticの目的は、変数/メソッドがクラスのインスタンスの代わりにクラスに属することです。

あなたの場合、それぞれの敵が自分の健康状態を維持したいと考えています。これは静的にすることはできません。 そして、そのクラスのシーン内にいくつのインスタンスがあるのか​​を数えたいとします。だから静的です。

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... 
    } 
} 

これはかなり簡単です。最初の部分はすべて静的で、クラスに関連しています。 2番目の部分はインスタンスに関連しています。敵のプールを使い、同じインスタンスを複数回再利用する場合、OnActivateメソッドはシーン内で敵を生き残らせるときに呼び出されます(非アクティブとしてしばらくの間そこにあったかもしれません)。それから、健康状態が悪化したら、敵を殺してください(必要なすべてのアクションがそこにあるわけではありません...)。

public staticプロパティを使用すると、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についての手掛かりを持っていないし、そのまま他のゲームで再利用することができるということです。 GameManagerは、より高いレベルのエンティティであり、それを知っています。

+0

私はイベントを使用するのが好きですが、あなたが静的を使用しなかった場合、私はさらにその解決法を気に入っています。しかし、良い解決策を提供するためにアップアップを持っています。 –

+0

ここには静的なものが実際には適切です。敵の数はEnemyクラスに関係します。また、より高いレベルのマネージャーで達成することもできます。 Enemyインスタンスが存在しない場合でも、EnemyCountの値を確認することができます。静的がここでは有効でない場合、一般的にプログラミングには全く理由がありません。 – Everts

関連する問題