比较两种不同类型的列表中的变量

时间:2017-02-25 00:49:21

标签: c# unity3d unity5

我正在使用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的序列化......

所以基本上,我可以轻松地比较这些变量吗?如果是这样,怎么样?

编辑:回答了我自己的问题

3 个答案:

答案 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应该仍然可以处理它。