【发布时间】:2020-03-27 07:24:51
【问题描述】:
我在 Unity、c# 中为我的员工保存任务时遇到问题。我将他们的任务实现为像命令模式一样使用方法(协程)作为任务算法。现在我必须将他们的任务保存到磁盘并稍后加载以恢复它们。
例子:
任务界面:
interface IEmployeeTask
{
IEnumerator PerformTask();
}
employee.cs
...
public WorkOnTask(IEmployeeTask task)
{
this.currentTask = task;
StartCoroutine(task.PerformTask());
}
...
两个任务实现:
class SomeTask1 : IEmployeeTask
{
...
public SomeTask1(int someImportantParameter){...}
public override IEnumerator PerformTask
{
assignedEmployee.GoThere();
yield return new WaitUntil(() => assignedEmployee.ReachedDestination);
assignedEmployee.DoThis();
yield return new WaitUntil(() => assignedEmployee.DidThis);
assignedEmployee.UseParameter(someImportantParameter);
}
}
class SomeTask2
{
...
public SomeTask2(SomeClass someImportantReference){...}
public override IEnumerator PerformTask
{
IThinkYouKnowWhereThisIsGoing();
LemmeJustUseSomeObject(someImportantReference);
yield break;
}
}
我无法重新启动这些任务,因此仅通过 new 或 Activator 创建任务并分配引用将无济于事。
我可以创建一个保存类并创建抽象 TaskSave IEmployeeTask.GetSave() 和 IEmployeeTask.LoadFrom(TaskSave save) 并为每个任务实现一个类,其中包含一些丑陋的 public readonly int referenceIds,但如果有机会我可以避免创建所有这些类并保留代码干净,我很想知道是否可能。
【问题讨论】:
-
为什么不能重启任务?不能再打
StartCoroutine(task.PerformTask())吗?我很难理解你的问题。这是关于将任务保存到磁盘以在会话之间使用还是您的意思是保存为在会话期间暂停任务? -
我无法重新启动它,因为如果任务中的某些事情被执行两次或更多次,那将是愚蠢的。我必须将其保存在外部,然后重新创建任务状态。
-
再想你的情况是不同的,因为你正在使用委托,你将无法序列化它。也许要构建您的任务,使用反射和外部文件(方法列表)来动态运行委托?为您提供更广阔的竞争环境。即使将代表排队并在外部获取/保存 int 索引(状态)也可以(但您会丢失沿途所做的引用)。
-
一个简单的答案是用单独的对象表示各个步骤,然后将它们序列化为 JSON。然后,制作一个可以构建任务的工厂。在我看来,你过于复杂了。您想保存有关任务的数据,而不是有关其行为的数据。如果您有
Step对象,那么Task对象可能只是一个Steps 数组和一个指向当前步骤的integer。这整个结构是可序列化的。 -
关键是将行为方面与数据驱动方面分开。任务中的任务或步骤仍然可以由协程启动,但任务或步骤的状态由数据定义(而不是其行为);您可以对其进行序列化和反序列化。工厂的职责可能是反序列化保存的任务,重新创建状态并返回完整的任务对象。然后
PerformTask方法可以简单地检查必须运行的步骤,类似于我之前的评论。
标签: c# unity3d coroutine strategy-pattern saving-data