【发布时间】:2015-01-04 07:00:29
【问题描述】:
我的一个项目存在设计问题。
我有 3 个班级:Planet、Star、Ship。这些类附加到相应的预制件并包含名称、位置、大小等数据。Planet 预制件附加了Planet 类,而不是其他类。 Star 预制件具有 Star 类,Ship 预制件具有 Ship 类。
还有一个名为SelectObject 的类,它处理选择功能(当用户单击预制件时)。基本上,它显示在所选对象的小窗口图像中,以及从附加到预制件的相应类中提取的一些数据。此类附加到所有可单击/可选择的对象:Planet、Star 和 Ship。
现在,我正在尝试让它变得更智能并尝试使用泛型,以便 SelectObject 可以处理任何当前和未来的类。当我只有 Planet 对象作为可选对象时,我声明:
public Planet planet;
如果选择了行星,则将数据分配给此 var,然后使用此 var 填充迷你窗口上的信息。 但是现在我有 3 个类,我不想“硬编码”并为每个添加类创建新变量。我想使用一个变量,它可以是 3 个(未来可能更多)类中的任何一个。
起初我以为我会声明 public System.Object myObject; 并使用泛型来分配其中的任何内容:
public System.Object myObject;
public T Set<T>(T param)
{
myObject = param;
return param;
}
这是一种方式 - 分配给一个对象没有问题,然后将它检索回行星我得到InvalidCastException: Cannot cast from source type to destination type。
那么,一个类有 3 个变量并有一个重载方法来返回一个非 null 变量是唯一的方法吗?或者有什么奇特的方法吗?
PS:经过一番研究,我找到了 .NET 4.0 的 dynamic 关键字,我认为这可以解决我遇到的问题。但是Unity好像不支持4.0?
感谢您的任何见解。
编辑 1: 澄清我的项目中目前正在发生的事情。我有 3 个预制件:船、星、行星。每个预制件都附加了 SelectObject 类。每个预制件还附加了一个相应的数据类,包装在预制件类中。所以最后,每个预制件都有 2 个附加到它的类。另一个脚本加载包含行星/船舶/恒星数据的数据文件,实例化相应的预制件并在预制件中填充相应的数据类。
SelectObject 具有OnMouseDown 函数,当用户单击其中一个实例化的预制件时,它应该从 GameObject 中提取数据类。这是我遇到问题的时候:((Prefab)(selObj.GetComponent(typeof(Prefab)))).myObject myObject 属于System.Object 类型,应该包含 Ship、Planet 或 Star 类型的类。但是,当我尝试从 Object 转换回它应该是的任何类时,我收到上述错误消息。
进一步增加混乱:如果我有一个简单的测试脚本,例如:
public string myObjectType;
public System.Object myObject;
...
Planet myPlanet = new Planet();
myPlanet.Name = "whatever";
myPlanet.Size = "BIG";
myObject = myPlanet;
...
稍后当我尝试从Object 中提取Planet 类时,它可以工作((Planet)myObject).Name。但是,当我从GameObject 提取Object 时采用更复杂的方法时,它会失败......我不知道为什么。
编辑 2:
我找到了为什么我从System.Object 初始转换回相应类型失败的原因。当我实例化 GameObject 时,System.Object 变量似乎丢失了它的类型。这很奇怪,因为Planet 类型的另一个变量很好。我将进一步调查,但到目前为止,如果我实例化一个附加了一个类的 GameObject,并且该类有一个 System.Object 变量,并且你为其分配了一些东西,那么在实例化过程中就会丢失一些东西。
因此,解决此问题的快速方法是:在加载数据和实例化预制件时,在调用 Instantiate 函数以物理创建游戏对象后,再次分配 System.Object 变量。这是一段代码:
// this is where I create a GameObject. Its not instantiated yet. System.Object variable inside newPlanet3 is assigned and correct
GameObject newPlanet3 = CreateStellarObject(myPlanet);
// this piece actually instantiates the object and places in the proper position
GameObject newPlanet2 = Instantiate(newPlanet3, myPlanet.position, Quaternion.identity) as GameObject;
// this is the fix. After instantiate, System.Object variable inside newPlanet2 is lost. Need to reassign it.
((Prefab)(newPlanet2.GetComponent(typeof(Prefab)))).myObject = ((Prefab)(newPlanet3.GetComponent(typeof(Prefab)))).myObject;
我不明白为什么会这样。实例化后我不需要重新分配其他变量。
【问题讨论】: