将GameObject转换回泛型类型<t>

时间:2018-01-01 16:52:16

标签: c# unity3d serialization deserialization deep-copy

我正在为Unity实施深度对象复印机。

我在这里找到了这个很棒的序列化/反序列化方法:https://stackoverflow.com/a/78612/3324388

然而,我遇到了MonoBehaviour对象。如果类型是GameObject,我需要使用Instantiate而不是序列化。所以我添加了一张支票:

if (typeof(T) == typeof(GameObject))
{
    GameObject clone = Instantiate(source as GameObject);
    T returnClone = clone as T;
    return returnClone;
}

我可以将源代码转换为GameObject(使用as),但当我尝试反向执行时,它会失败

  

类型参数T不能与as参数一起使用,因为   它没有类类型约束,也没有“类”约束。

如果我试着像它一样:

if (typeof(T) == typeof(GameObject))
{
    GameObject clone = Instantiate(source as GameObject);
    T returnClone = (T)clone;
    return returnClone;
}
  

无法将GameObject转换为T

类型

我觉得我很接近,但我不能完全正确地进行投射。你知道我缺少什么才能让它发挥作用吗?

如果我将类型转换为符合,则错误仍然存​​在: enter image description here

2 个答案:

答案 0 :(得分:4)

它不漂亮,但您可以强制编译器执行先前的引用转换为object

 public static T Clone<T>(T source)
 {
      if (source is GameObject)
      {
          return (T)(object)Instantiate((GameObject)(object)source);  
      }
      else ...
  }

是的,这有点黑客但有时你无法避免它。作为一般规则,当您开始将泛型与运行时类型检查混合时,事情往往会变得混乱,这肯定表明您可能不应该首先使用泛型。但有时候,它可能是合理的,但丑陋的代码往往会出现。

答案 1 :(得分:4)

在return语句中使用as T似乎可以解决问题。在下面附加到场景中游戏对象的测试代码中,我看到了Test的副本,控制台显示了Count的不同值:

public class Test : MonoBehaviour
{
    private static bool _cloned = false;

    public static T Clone<T>(T source) where T : class 
    {
        if (typeof(T) == typeof(GameObject))
        {
            GameObject clone = Instantiate(source as GameObject);
            return clone as T;
        }
        else if (typeof(T) == typeof(PlainType))
        {
            PlainType p = new PlainType();
            // clone code
            return p as T;
        }
        return null;
    }

    public class PlainType
    {
        private static int _counter = 0;
        public int Count = ++_counter;
        public string Text = "Counter = " + _counter;
    }

    public PlainType MyPlainType = new PlainType();

    void Update ()
    {
        if (!_cloned)
        {
            _cloned = true;
            Clone(gameObject);
            PlainType plainClone = Clone(MyPlainType);
            Debug.Log("Org = " + MyPlainType.Count + " Clone = " + plainClone.Count);
        }
    }

}