分配事件以使用新订阅

时间:2017-06-06 13:56:28

标签: c# events delegates event-handling

我正在统一制作QuestSystem。

我想要做的是为我的questData分配一个事件,以便知道任务目标何时完成。

假设有一个名为A的类和名为a的行动。

我想要课程B,操作b想要引用A.a

所以如果我这样做

b = A.a;

b+= someAction;,它实际上是a+=someAction;

但如果我这样做的话。它只是b+=someActionA.a将保持null

我应该怎样做才能完成我想要的事情?

这里有一些标签。 (我不知道答案是什么。所以..)

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

======编辑======= 这是我的代码。

QuestData.cs

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,
                },
            }
        };
    }


}

2 个答案:

答案 0 :(得分:1)

一个可能的解决方案是创建一组新的EventArgs,如下所示:

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

(可能在另一个档案中) ......并像这样使用它:

首先,创建一个事件委托:

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

实例化事件委托:

public event QuestObjectiveCompletedHandler CompletedObjective;

定义在目标完成时将执行某些操作的方法:

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

将该方法分配给事件:

this.CompletedObjective += this.ObjectiveCompleted;

从这里开始,您可以在FinishedObjectiveQuestCompletedEventArgs以及List<QuestObjective>中随时生成FinishedObjective.add(objectiveIn)个对象。

当完成一定数量的目标或者你想对这些信息做什么时,你也应该能够使事件处理方法采取不同的行为。

当然,只要新方法的签名带有相同的签名,您还可以通过添加更多this.CompletedObjective += this.methodName;行来添加多种不同的方法来响应此事件。

答案 1 :(得分:0)

在阅读您的示例时,我写了一些代码,其中“A”为QuestObjective,“B”为QuestQuest对象需要知道目标何时被标记为已完成。

使用事件处理程序,我们可以对其进行设置,以便在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
        }
    }
}