我在试着创建一个任务系统。我有继承接口的QuestCreator、Quest和多个目标类(TalkObjective、LocationObjective等)。
在Quest类的构造函数中,我创建了一个类似List<IObjective>的列表。它没有起作用。
然后我创建了一个类来保存所有不同类型的列表。但我失去了对目标进行排序的能力。
我的问题是:有没有更好的方法/设计来做到这一点?
编辑
我很抱歉我没有详细描述它。因为我更改了我的代码,所以我不能在这里发布它。我试图创建相同的代码,但这一次代码没有给我错误。所以我自己解决了这个问题。
我使用的是一个没有完成/废弃的教程。Here is the link to github
我用抽象类构建了我的商品/库存系统,这是我想到的第一件事。但我的意图是按照教程的创建者设计的方式创建这个任务系统,这样我就可以学习他的方式。
我希望将不同对象类的对象放在一个列表中,并使用它们共同使用的接口。
public class QuestCreator : MonoBehaviour {
#region fields
private List<IQuestObjective> objectives;
private GameObject itemManager;
private ItemDatabase itemdb;
private Location location;
private Quest quest;
//For Saving Quest
private Quest_data quests;
#endregion
void Update()
{
//Just for the test purpose
if (Input.GetKeyDown (KeyCode.E))
{
itemManager = GameObject.Find ("GameManager");
itemdb = itemManager.GetComponent<ItemDatabase>();
Item item = new Item ();
Item item2 = new Item ();
item = itemdb.weapon_database[0];
item2 = itemdb.weapon_database [1];
CollectionObjective collectionObjective = new CollectionObjective ("Find", 3, item, "Find this precious item");
CollectionObjective collectionObjective2 = new CollectionObjective ("Find", 1, item2, "Find Sword of Warrior from Dark Passage");
LocationObjective locationObjective = new LocationObjective ("Go to Green Valley", "Go to " + location, location, false);
objectives = new List<IQuestObjective> ();
objectives.Add(collectionObjective);
objectives.Add (collectionObjective2);
objectives.Add (locationObjective);
QuestText questText = new QuestText ();
QuestIdentifier questIdentifier = new QuestIdentifier();
questText.Title = "Finding Sword of Warrior";
questText.DescriptionSummary = "Summary...";
questText.Hint = "Hint...";
questIdentifier.QuestID = 1;
questIdentifier.SourceID = 1;
quest = new Quest (questIdentifier, questText, objectives);
Debug.Log (quest.Objectives[1].Description);
Debug.Log (quest.Objectives.Count);
}
}发布于 2017-01-26 15:43:43
您需要研究继承和多态性。
在您的示例中,您将拥有一个包含所有常见逻辑的IObjective类:
public abstract IObjective : MonoBehaviour
{
public abstract void CommonMethod();
public virtual void OverrideIfNeeded(){}
public void UseAsIs(){}
}CommonMethod必须被子类重写。OverrideIfNeeded可以被覆盖或按原样使用。UseAsIs不能被覆盖(但它可以被隐藏)。
然后你就有了一个集合:
IEnumerable<IObjective> collection;它包含各种不同的对象,这些对象都是IObjective,您可以迭代和调用IObjective中的所有方法:
foreach(IObjective obj in collection)
{
obj.CommonMethod();
obj.UseAsIs();
...
}发布于 2017-01-26 15:27:19
首先,对于所有的游戏编程,我强烈建议通过这本网络书籍- http://gameprogrammingpatterns.com/contents.html (它也提供PDF/书籍的变体为一些钱)。它会帮助你做一些游戏模式的例子,你会对游戏是如何制作的有一个概念。
你的问题有点宽泛,涉及到每个人的观点,不应该被列为Q on SO,但是:
逻辑上对我来说是这样的:有一个Quest (由工厂QuestCreator创建),它包含List<Objectives>。
Objectives应该是一个抽象的类,包含一些变量和方法( Objective完成了吗?-所有objective都有的其他东西)。
在此之后,您应该继承较小的对象(如TalkObjective、ItemObjective),并覆盖-> IsObjectiveDone方法的内部实现。
老实说,在游戏编程中,开发人员正在尽可能地避免继承。创建继承树然后遍历代码太难了。取而代之的是,他们试图依赖像Component这样的模式(与上面的源代码相同)。
添加一些示例:
public abstract class Objective
{
public bool IsObjectiveDone { get; private set; }
public virtual void CheckIfDone();
}
public class ObjectiveGroup
{
public bool AllObjectivesDone => SubObjectives.All(a => a.IsObjectiveDone);
public Objective[] SubObjectives { get; private set; }
public static ObjectiveGroup Create(TypeOfQuest aType, Requirements[] aReq)
{ /* factory implementation */ }
}一旦你有了上面的例子,你就可以定义每种类型的“特殊”目标:
public class ItemObjective : Objective
{
public Item RequiredItem { get; private set; }
override public void CheckIfDone()
{
this.IsObjectiveDone = Player.GetInstance().Inventory.Contains(RequiredItem);
}
}一旦你想要开始新的任务,你将呼叫工厂,它将创建任务,包含一组目标。在每个目标上,您将在用户每次执行某些操作/获取新项目时执行CheckIfDone操作。
public class Quest
{
public ObjectiveGroup { get; private set; }
public Quest(TypeOfQuest aType, Requirements[] aReq)
{
this.ObjectiveGroup = ObjectiveGroup.Create(aType, aReq);
}
}
public class Player
{
public List<Quest> Quests = new List<Quest>();
public List<Item> Inventory = new List<Item>();
}
public void Main(/* ... */)
{
Player player = new Player();
player.Quests.Add(new Quest(TypeOfQuest.ItemObtain, new Requirements[] { Item["Sword of Conan"] });
while(true)
{
player.Quests.ObjectiveGroup.ForEach(a => a.SubObjectives.ForEach(b => b.CheckIfDone()));
foreach(var objGrp in player.Quests.ObjectiveGroup)
if(objGrp.IsObjectiveDone) Console.WriteLine("Quest completed");
}
}发布于 2017-01-26 15:35:26
以下是您可能针对您的问题而编写的代码示例。
public class Program
{
public struct Location
{
// Assumes 2D game location
public int X;
public int Y;
}
public struct Character
{
public int GameCharId;
}
public class BaseObjective
{
public string Title;
public string Description;
}
public class TalkObjective : BaseObjective
{
public Character TargetCharacter;
}
public class LocationObjective : BaseObjective
{
public Location TargetLocation;
}
public static void Main(string[] args)
{
List<BaseObjective> currentObjectives = new List<BaseObjective>();
TalkObjective obj1 = new TalkObjective(){ Title = "Talk to Bob", Description = "Bob has some useful information for you", TargetCharacter = new Character(){GameCharId = 87}};
LocationObjective obj2 = new LocationObjective(){ Title = "Find the thing", Description = "Bob informed you of a thing, go and find it", TargetLocation = new Location(){ X = 33, Y=172}};
currentObjectives.Add(obj1);
currentObjectives.Add(obj2);
}
}https://stackoverflow.com/questions/41868468
复制相似问题