【问题标题】:Comparing variables in Lists of two different types比较两种不同类型列表中的变量
【发布时间】:2017-02-25 14:43:43
【问题描述】:

我正在使用 Unity3D 创建类似于最终幻想等的 RPG 游戏。当然是在 c# 中。

对于游戏中的实体,有两个单独的类:角色和敌人。

对于我的战斗代码,我有两个列表,一个列表称为派对,一个列表称为敌人。 我经常需要一起比较和修改 ALL Characters 和 Enemies 的 int 值,这很难做到,因为它们在单独的列表中。它们具有相同名称的相同变量,例如(int Reflex, int Attack, int Strength, int Defense, etc.) 但它们是不同的类型,所以我不知道该怎么做,例如,从两个列表中获取具有最高反射的角色或敌人.

我的直接倾向是将它们用作派生类,让 Character 和 Enemy 都从基类 Entity 继承,其中包含它们的重叠变量。然后我可以在战斗中使用一份实体列表。简单多了,但是该死的 Unity3D 不支持其序列化过程的多态性,目前我所有的保存和加载都依赖于此。

我希望有一个更简单的答案;否则,我将不得不痛苦地重写我所有的保存和加载代码,以某种方式不使用 Unity 的序列化......

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

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

【问题讨论】:

  • “但是该死的 Unity3D 不支持其序列化过程的多态性,目前我所有的保存和加载都依赖于它。” 我对此不确定,但请包括代码。包括您所做的示例代码,然后人们可以帮助您解决问题。

标签: c# unity3d unity5


【解决方案1】:

在提出这个问题后这么快,这可能有点荒谬,但我意外地看到了一篇非常好的博客文章,描述了我遇到的相同问题: http://www.archmagerises.com/news/2015/9/22/tips-on-game-world-state-data-serialization-in-unity-c

按照他的例子,我在我的游戏中实现了SharpSerializer。它工作得很好,我回到了我最初计划的多态类系统。 现在我不必试图强迫我的代码绕过 Unity 糟糕的内置序列化程序。

我想发布这个,因为在 Unity 论坛或这里似乎没有很多帖子可以解决这个问题,所以任何人和我有同样问题的人都可以找到一个很好的解决方案。

【讨论】:

  • 我使用 Unity 内置的 Json 序列化程序执行此操作,它工作得非常好,但如果这对你有用,那就去吧。
【解决方案2】:

Unity 的内置序列化程序可能需要做很多工作,但我真的只是在编写编辑器脚本时遇到了非常头疼的问题。就像,我非常同情this 家伙的愤怒。运行时序列化有点不同,使用起来更容易一些,尤其是在 Unity 的 JsonDotNet 等外部工具的帮助下,或者我看到你在其他地方提到过 SharpSerializer。还有FullSerializer 和它的资产商店分支FullInspector,专门用于帮助解决那些令人沮丧的编辑器脚本问题。

需要注意的几点:Unity 确实支持 UnityEngine.Object 派生类的多态性,这当然包括 MonoBehaviour。至于自定义类,如果这些类具有默认情况下unity无法序列化的属性(例如Dictionary),则可以实现ISerializationCallbackReciever接口。否则,您只需将 [Serializeable] 标记添加到类中,让 unity 知道您希望保存该数据。您还应该熟悉其他一些注意事项,请参阅: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;

}

像 Json.NET for Unity 等序列化解决方案。人。在使序列化过程更容易方面大有帮助,但无论您使用什么解决方案,关注数据将如何被序列化都非常重要。

我个人会为 Unity 推荐 Json.Net,但我使用过的唯一其他资产是 FullSerializer 和 FullInspector。我没用过SharpSerializer。

【讨论】:

    【解决方案3】:

    为什么不使用带有 ID 字段的 Plain Old C# 类来抽象出 Characters 和 Enemies 的数据呢? (可能称为“CreatureData”、“ActorData”或“CharacterData”)。然后这个抽象类的每个实例都可以引用这个包含在 Characters 和 Enemies 中的新 ID 字段。

    然后可以将新 C# 类的实例存储在另一个集合中,例如字典或列表,并在以后轻松迭代。

    除非我弄错了,只要你使这个新类可序列化,Unity 应该仍然能够处理它。

    【讨论】:

    • 这是一个选项,但由于所有内容都是嵌套的方式,需要花费大量时间和精力(只保存了一个对象,游戏,其中包含其他对象的数组,这些对象都是自定义类,并且这些自定义类包含其他自定义类、自定义结构等)编辑:但我在下面回答了我自己的问题,所以我感到非常满意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 2018-04-24
    • 2020-10-12
    • 2014-11-12
    • 1970-01-01
    相关资源
    最近更新 更多