2017-06-06 2 views
0

私はQuestSystemを統一しています。C#新しい{}でsubscibeにイベントを割り当てる

クエストの目的が完了したときにわかるように、クエストデータにイベントを割り当てることができます。

Aという名前のクラスとaという名前のクラスがあるとします。

と私はクラスBAction bA.a

への参照を持っていると思いますが、私は

b = A.a;

b+= someAction;をすれば、それは実際にa+=someAction;

を行いますが、ときに私がしなければしたいですそれ。それは単にb+=someActionとなり、A.aは残りますnull

私は何をしたいのですか?

ここにいくつかのタグがあります。編集======= ======(私は答えがどうなるか分からない。そう...)

# event 
# subscribing event 
# assigning event 
# referencing event 
# action 
# delegate 

ここに私のコードです。

public class QuestData 
{ 
    public string questName; 
    public string qusetID; 
    public string questDescription; 
    public SceneType questSceneType; 

    private string isActivePrefsKey { get { return $"QuestKey{qusetID}"; } } 
    public bool isActive { 
     get { 
      return Convert.ToBoolean (PlayerPrefs.GetInt (isActivePrefsKey)); 
     } 
     set { PlayerPrefs.SetInt (isActivePrefsKey, Convert.ToInt16 (value)); } 
    } 
    public QuestObjective questObjective; 
    public QuestReward questReward; 


    public void Activate() 
    { 
     if (AppController.CurrentScene == questSceneType) { 
      questObjective.ActivateObjective(); 

     } 
    } 

} 

QuestObjective.cs

public class QuestObjective 
{ 
    // TODO rename all 
    public int goalObjectiveCount; 
    public int currentObjectiveCount; 


    public Action questAction; 

    public void OnConditionMatch() 
    { 
     Debug.Log ("OnConditionMatch"); 
     currentObjectiveCount += 1; 
    } 

    public void ActivateObjective() 
    { 
     questAction += OnConditionMatch; 
    } 


} 

QuestManager.cs

あなたの例に読む
public class QuestManager : MonoBehaviour 
{ 

    List<QuestData> questDatas; 


    void Awake() 
    { 
     PrepareQuestDatas(); 
     ActivateActiveQuests(); 
    } 


    void ActivateActiveQuests() 
    { 
     var activeQuests = GetActiveQuests(); 
     foreach (var activeQuest in activeQuests) { 
      activeQuest.Activate(); 
     } 
    } 


    List<QuestData> GetActiveQuests() 
    { 
     // for debuging 
     return questDatas; 

     // real code 
     return questDatas.Where (q => q.isActive == true).ToList(); 
    } 



    public void PrepareQuestDatas() 
    { 
     questDatas = new List<QuestData> { 
      new QuestData { 
       questName = "Foot Print", 
       questDescription = "win the game for first time", 
       questSceneType = SceneType.Main, 
       questObjective = new QuestObjective { 
        goalObjectiveCount = 1, 
        questAction = GamePlayController.instance.endGameCon.onWinGame 
       }, 
       questReward = new QuestCoinReward{ 
        rewardAmount = 100, 
       }, 
      } 
     }; 
    } 


} 
+0

あなたに聞いている質問への答えは、「B」に問題の「A」への参照を与えることです: 'B.MyReferenceToSomeA.a + = someAction;'しかし、私はこれが[ XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)を参照してください。 –

+1

*私は何が欲しいか分からない。だから.. * - おそらく、あなたの問題についてもっと正確にしようとするべきです。 – Adrian

+0

@adjanが編集しました。私は確かに私が欲しいものを知っているでしょう – uzu

答えて

0

QuestData.csは、私が "A" であり、いくつかのコードを書かれていますQuestObjectiveであり、「B」はQuestである。 Questオブジェクトは、目的が完了としてマークされたときを知る必要があります。

アクションは次のようにA.

に発生したときにBが通知されるように、イベントハンドラを使用して、我々はそれを設定することができます

// B 
public class Quest 
{ 
    public Quest() 
    { 
     Objectives = new List<QuestObjective>(); 
     // load objectives... Fake 
     Objectives.Add(new QuestObjective("obj 1")); 
     Objectives.Add(new QuestObjective("obj 2")); 
     Objectives.Add(new QuestObjective("obj 3")); 

     foreach(var o in Objectives) // subscribe to QuestObjective events 
     { 
      o.ObjectiveCompleted += (sender, args) => ReportObjectiveCompleted(); 
     } 
    } 

    public void ReportObjectiveCompleted() 
    { 
     // let 'em know 
    } 

    public List<QuestObjective> Objectives { get; set; } 
} 

// A 
public class QuestObjective 
{ 
    public string Name { get; set; } 
    public QuestObjective(string name = "unknown") 
    { 
     Name = name; 
    } 
    public event EventHandler ObjectiveCompleted; 

    public void MarkCompleted() 
    { 
     // when a task is marked as complete and IF there are 
     // subscribers to this event then call the event handler 
     var a = ObjectiveCompleted; 
     if (a != null) 
     { 
      a(this, new EventArgs()); // use different event args to pass data 
     } 
    } 
} 
+0

お返事ありがとうございます。 (あなたのコードで)しかし、私は欲しいものは、どのイベントがQuestObjectiveに完了するように伝えるのですか。 いくつか好きです。 via new QuestObjective {eventToSubscribe = GameController.onWinGame} – uzu

+0

あなたの 'QuestObjective'実装は私にとって紛らわしいものです。 'Action'を間違って使用しています。あなたの 'PrepareQuestDatas'メソッドと' QuestObjective.ActivateObjective'で 'questAction'を設定していますが、' questAction() ' - これを呼び出すべきときは? –

+0

thats質問です。私はアクションを使用している理由は、それに割り当てられているイベントを購読することです。 私は義務付けられた行動を呼びたくはありません。私はactonを割り当てることによって呼び出されるアクションが欲しい。 – uzu

1

一つの潜在的解決策がいるEventArgsの新しいセットを作成することです、このような:

public class QuestCompletedEventArgs : System.EventArgs 
{ 
    public QuestObjective FinishedObjective { get; } 
    public QuestCompletedEventArgs(QuestObjective objectiveIn) { 
     this.FinishedObjective = objectiveIn; 
    } 
} 

(おそらく別のファイルに) ...そして、このようにそれを使用します。

まず、イベントのデリゲートを作成:

public event QuestObjectiveCompletedHandler CompletedObjective; 

目的が完了したときに何かをするメソッドを定義します:

public delegate void QuestObjectiveCompleteHandler(object sender, QuestCompletedEventArgs e); 

がイベントデリゲートのインスタンスを作成します

public void ObjectiveCompleted(object sender, QuestCompletedEventArgs e) 
{ 
    // do something 
} 

このメソッドをイベントに割り当てる:

this.CompletedObjective += this.ObjectiveCompleted; 

ここから、あなたはQuestCompletedEventArgsList<QuestObjective>FinishedObjectiveオブジェクトを作成し、FinishedObjective.add(objectiveIn)適切な場合はいつでもできます。

また、一定の目的が完了したとき、またはその情報で何をしたいときでも、イベント処理方法を異なるようにすることができます。

もちろん、新しいメソッドのシグネチャが同じシグネチャを持つ限り、this.CompletedObjective += this.methodName;行を追加してこのイベントに応答する複数の異なるメソッドを追加することもできます。

+0

そう...それは機能しましたか? – Sal

関連する問題