我正在使用Unity3D创建类似于最终幻想等的RPG游戏。在c#当然。
对于游戏中的实体,有两个不同的类:角色和敌人。
对于我的战斗代码,我有两个列表,一个名为Party的List,一个名为Enemies的List。 我经常需要将所有角色和敌人的int值进行比较和修改,这很难做到,因为它们位于不同的列表中。它们具有相同名称的相同变量,例如(int Reflex,int Attack,int Strength,int Defense等)但是它们是不同的类型,所以我不知道要做什么,例如,从两个列表中获得具有最高Reflex的Character OR Enemy,例如
我的直接倾向是将它们用作派生类,让Character和Enemy继承自基类Entity,其中包含重叠变量。然后我可以在战斗中使用一个实体列表。更容易,但该死的Unity3D不支持其序列化过程的多态性,我的所有保存和加载当前都依赖于它。
我希望有一个更简单的答案;否则,我将不得不痛苦地重写我的所有保存和加载代码,不知何故,不使用Unity的序列化......
所以基本上,我可以轻松地比较这些变量吗?如果是这样,怎么样?
编辑:回答了我自己的问题
答案 0 :(得分:1)
在提出这个问题后不久,这可能有点荒谬,但我出乎意料地发现了一篇非常好的博文,描述了我遇到的同样问题: http://www.archmagerises.com/news/2015/9/22/tips-on-game-world-state-data-serialization-in-unity-c
按照他的例子,我在游戏中实现了sharpSerializer。它工作得很好,我回到了我最初计划的多态类系统。 现在,我不必尝试强制我的代码解决Unity内置的串行器。
我想发布此消息,因为在Unity论坛或者解决此问题的地方似乎没有很多帖子,所以任何人都有同样的问题,我可以找到一个很好的解决方案。
答案 1 :(得分:1)
Unity的内置序列化程序可以使用很多工作,但我在编写脚本时却真的遇到了巨大的麻烦。就像,我非常同情this家伙的愤怒。运行时序列化有点不同,它更容易使用,尤其是在Unity等JsonDotNet之类的外部工具的帮助下,或者我看到你在其他地方提到SharpSerializer。还有FullSerializer,它是资产商店分支FullInspector,专门用于帮助处理那些令人沮丧的编辑器脚本头痛。
有几点需要注意:Unity确实支持UnityEngine.Object派生类的多态性,当然这包括MonoBehaviour。对于自定义类,如果这些类具有默认序列化不能统一的属性(如Dictionary),则可以实现ISerializationCallbackReciever接口。否则,您只需将[Serializableable]标签添加到类中,让团结知道您希望保存这些数据。您应该熟悉一些其他注意事项,请参阅:https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
以您的用例为例,通常的结构可能如下所示:
[Serializeable]
public Class ActorProperties{
public int CurrentHealth;
public int MaxHealth;
public int Range;
}
public Class Actor : MonoBehaviour{
[SerializeField] protected ActorProperties _actorProperties
public ActorProperties ActorProperties{
get{ return _actorProperties;}
set{_actorProperties = value;}
}
}
public Class Character : Actor{
// Character specific code
}
public Class Enemy : Actor{
// Enemy specific Code
}
public Class GameManager : MonoBehaviour{
private List<Actor> enemies;
private List<Actor> characters;
public List<Actor> AllActors{
get{
List<Actor> returnList = new List<Actor>(characters);
returnList.AddRange(enemies);
return returnList;
}
}
public Actor GetActorWithHealth(float healthCheck){
Actor actor = AllActors.Find(x => x.ActorProperties.CurrentHealth == healthCheck);
return actor;
}
}
除了非序列化数据类型之外,下面的示例说明了需要自定义序列化时最常见的实例。
// Even though Properties is marked as Serializeable, it's 'data' property
// won't get serialized if we're serializing a reference to an ActorProperties.
// No native support for polymorphic serialization of custom classes.
[Serializable]
public class Properties{
public float data;
}
[Serializeable]
public class ActorProperties : Properties{
// Here we have a recursion problem because Unity cannot serialize
// null values for custom classes. Unity will try to serialize this ActorProperties field, which in turn starts the serialization over again,
// with an iteration depth of 7. Killer if it were a List<ActorProperties> .
public ActorProperties EnemyProperties;
public int CurrentHealth;
public int MaxHealth;
public int Range;
// Since Unity treats custom classes like structs, the following field wont be serialized
// as a pointer to an existing object, but as a unique instance of it's class.
public CustomClass SharedReference;
}
用于Unity等的Json.NET等序列化解决方案。人。大大简化了序列化过程,但无论使用何种解决方案,都要注意精确地将数据序列化。
就个人而言,我会推荐Json.Net用于Unity,但我唯一拥有的其他资产是FullSerializer和FullInspector。我没有使用SharpSerializer。
答案 2 :(得分:0)
为什么不使用带有ID字段的普通旧C#类抽象出人物和敌人的数据? (可能称为“CreatureData”“ActorData”或“CharacterData”)。然后,此抽象类的每个实例都可以引用包含在角色和敌人中的新ID字段。
然后可以将新C#类的实例存储在某种类型的集合中,如字典或列表,并在以后轻松迭代。
除非我弄错了,只要你让这个新类序列化,Unity应该仍然可以处理它。