将 GameObject 转换回通用类型 <T>
Convert GameObject back to generic type <T>
我正在为 Unity 实现一个深度对象复制器。
我在这里找到了这个很棒的 serialization/deserialization 方法:
但是我遇到了 MonoBehaviour 对象的问题。如果类型是 GameObject,我需要使用 Instantiate
而不是序列化。所以我添加了一张支票:
if (typeof(T) == typeof(GameObject))
{
GameObject clone = Instantiate(source as GameObject);
T returnClone = clone as T;
return returnClone;
}
我可以将源转换为游戏对象(使用 as
),但是当我尝试反向执行时,它失败了
The type parameter T
cannot be used with the as
parameter because
it does not have a class type constraint nor a 'class' constraint.
如果我尝试像这样投射它:
if (typeof(T) == typeof(GameObject))
{
GameObject clone = Instantiate(source as GameObject);
T returnClone = (T)clone;
return returnClone;
}
Cannot convert GameObject to type T
我觉得我很接近,但我不能完全正确地选角。你知道我缺少什么才能让它工作吗?
如果我转换类型以符合错误仍然存在:
它不是很漂亮,但你可以强制编译器将先前的引用转换为 object
:
public static T Clone<T>(T source)
{
if (source is GameObject)
{
return (T)(object)Instantiate((GameObject)(object)source);
}
else ...
}
是的,这有点麻烦,但有时您无法避免。作为一般规则,当您开始将泛型与运行时类型检查混合使用时,事情往往会变得一团糟,这是您可能一开始就不应该使用泛型的明确信号。虽然有时候,它是合理的,但丑陋的代码往往会突然出现。
在 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);
}
}
}
我正在为 Unity 实现一个深度对象复制器。
我在这里找到了这个很棒的 serialization/deserialization 方法:
但是我遇到了 MonoBehaviour 对象的问题。如果类型是 GameObject,我需要使用 Instantiate
而不是序列化。所以我添加了一张支票:
if (typeof(T) == typeof(GameObject))
{
GameObject clone = Instantiate(source as GameObject);
T returnClone = clone as T;
return returnClone;
}
我可以将源转换为游戏对象(使用 as
),但是当我尝试反向执行时,它失败了
The type parameter
T
cannot be used with theas
parameter because it does not have a class type constraint nor a 'class' constraint.
如果我尝试像这样投射它:
if (typeof(T) == typeof(GameObject))
{
GameObject clone = Instantiate(source as GameObject);
T returnClone = (T)clone;
return returnClone;
}
Cannot convert GameObject to type
T
我觉得我很接近,但我不能完全正确地选角。你知道我缺少什么才能让它工作吗?
如果我转换类型以符合错误仍然存在:
它不是很漂亮,但你可以强制编译器将先前的引用转换为 object
:
public static T Clone<T>(T source)
{
if (source is GameObject)
{
return (T)(object)Instantiate((GameObject)(object)source);
}
else ...
}
是的,这有点麻烦,但有时您无法避免。作为一般规则,当您开始将泛型与运行时类型检查混合使用时,事情往往会变得一团糟,这是您可能一开始就不应该使用泛型的明确信号。虽然有时候,它是合理的,但丑陋的代码往往会突然出现。
在 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);
}
}
}