【问题标题】:Assigning event to subscribe with new分配事件以订阅新的
【发布时间】:2017-06-06 13:56:28
【问题描述】:

我正在统一制作 QuestSystem。

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

假设有一个名为 A 的类和一个名为 a 的操作。

我想要 Class B,Action b 想要参考 A.a

如果我这样做了

b = A.a;,

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

但是如果我这样做的话。它将只是简单地 b+=someAction 和 A.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,
                },
            }
        };
    }


}

【问题讨论】:

  • 您要问的问题的答案是给B 一个对有问题的A 的引用:B.MyReferenceToSomeA.a += someAction; 但我不确定这不是an XY Problem。
  • 我不知道我想要什么。所以.. - 也许您应该尝试更准确地了解您的问题
  • @adjan 已编辑。我当然知道我想要什么哈哈
  • 如果没有看到您的原始代码,我们将不知道如何对您现有的代码库进行更改。请发帖a minimal example of what needs to change,并详细说明需要修改的地方。您可能还想阅读How to Ask。

标签: c# events delegates event-handling


【解决方案1】:

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

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;

从这里,您可以将QuestCompletedEventArgs 中的FinishedObjective 对象设置为List&lt;QuestObjective&gt;,并在适当的时候将FinishedObjective.add(objectiveIn) 设置为。

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

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

【讨论】:

    【解决方案2】:

    读到你的例子,我写了一些代码,其中“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
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复。 (在您的代码中)但我想要的是告诉哪个事件告诉 QuestObjective 完成.. 一些喜欢这个。通过新的 QuestObjective{ eventToSubscribe = GameController.onWinGame }
    • 您的QuestObjective 实现让我感到困惑。您错误地使用了Action。您在 PrepareQuestDatas 方法和 QuestObjective.ActivateObjective 中设置 questAction - 但您从不调用它,如下所示:questAction() - 什么时候应该调用它?
    • 这就是问题所在。我使用动作的原因是订阅分配给它的事件。但我不知道如何.. 我不想调用 assiged 行动。我想要通过分配动作调用的动作。
    • 您需要将两个事件链接在一起。你目前的做法是
    • 我该怎么做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    相关资源
    最近更新 更多