Unity 3.5 至 4.0 升级指南
游戏对象的活动状态
Unity 4.0 改变了游戏对象活动状态的处理方式。游戏对象的活动状态现在由子游戏对象继承,因此,任何不活动的游戏对象也会使其子对象不活动。我们认为新行为比旧行为来得更有意义,应该始终如此。此外,即将发布的新 GUI 系统严重依赖新 4.0 行为,没有的话不太可能实现。不幸的是,这就要求做一些工作来修复现有工程,从而让它与新的 Unity 4.0 行为共同作用,以下列出了更改内容:
旧行为:
无论游戏对象是否活动,都以其 .active 属性进行定义。
可对其进行查询并勾选 .active 属性进行设置。
游戏对象的活动状态对子游戏对象的活动状态无影响。如果想激活或停用游戏对象及其所有子对象,须调用 GameObject.SetActiveRecursively。
对游戏对象调用 SetActiveRecursively 时,任何子游戏对象的先前活动状态将会丢失。使用 SetActiveRecursively 停用然后激活游戏对象及其所有子对象时,调用 SetActiveRecursively 前任何不活动的子游戏对象会变为活动状态,如果想恢复到原有状态,须手动记录子游戏对象的活动状态。
预设不包含任何活动状态,实例化后会始终保持活动状态。
新行为:
游戏对象活动与否由自身及其所有父游戏对象的 .activeSelf 属性定义。如果游戏对象自身及其所有父对象的 .activeSelf 属性设为 true,即为活动状态。如果其一设为 false,则为不活动状态。
可使用 .activeInHierarchy 属性进行查询。
游戏对象的 .activeSelf 状态可通过调用 GameObject.SetActive 进行更改。对先前活动的游戏对象调用 SetActive (false) 可停用该游戏对象及其所有子对象。如果所有父对象为活动状态,对先前不活动的游戏对象调用 SetActive (true) 可激活该游戏对象。所有父对象为活动状态(如所有父对象的 .activeSelf 设为 true)时,其子对象将激活。
这意味着不再需要 SetActiveRecursively,而是从父对象那里继承活动状态。还意味着调用 SetActive 停用和激活部分层级视图时,任何子游戏对象的先前活动状态将保留。* 预设可包含活动状态,并保留在预设实例化中。
示例:
有 A、B、C 三个游戏对象,那么 B 和 C 都是 A 的子对象。
调用 C.SetActive(false) 停用 C。
现在,A.activeInHierarchy == true,B.activeInHierarchy == true 且 C.activeInHierarchy == false。
同样,A.activeSelf == true,B.activeSelf == true 且 C.activeSelf == false。
现在我们调用 A.SetActive(false) 来停用父对象 A。
现在,A.activeInHierarchy == false,B.activeInHierarchy == false 且 C.activeInHierarchy == false。
同样,A.activeSelf == false,B.activeSelf == true 且 C.activeSelf == false。
现在我们调用 A.SetActive(true) 再次激活父对象 A。
现在,回到 A.activeInHierarchy == true,B.activeInHierarchy == true 且 C.activeInHierarchy == false。
同样,A.activeSelf == true,B.activeSelf == true 且 C.activeSelf == false。
编辑器的新活动状态
要将这些更改可视化,在 Unity 4.0 编辑器中任何不活动的游戏对象(因自身或父对象的 .activeSelf 属性设置为 false)将在层级视图中显示为灰色,在检视器中的图标也为灰色。游戏对象自身的 .activeSelf 属性通过其活动复选框体现,可进行切换,与父对象的状态无关(但如果所有父对象都是活动状态,就会激活该游戏对象)。
对现有工程的影响:
为了让用户了解代码中可能会受到影响的地方,GameObject.active 属性和 GameObject.SetActiveRecursively() 函数已被弃用。
但是它们依然起作用。GameObject.active 值的读取与 GameObject.activeInHierarchy 的读取相同,设置 GameObject.active 与调用 GameObject.SetActive() 相同。调用 GameObject.SetActiveRecursively() 与对游戏对象及其所有子对象调用 GameObject.SetActive() 相同。
3.5 版本中的现有场景通过将场景中任何游戏对象的 selfActive 属性设置为先前的 active 属性进行导入。
因此,只要不依赖拥有不活动游戏对象的活动子对象(在 Unity 4.0 中不再可行),从 Unity 旧版本中导入的任何工程应能如期工作(虽然会出现编译器警告)。
如果工程依赖于拥有不活动游戏对象的活动子对象,就必须更改 Unity 4.0 中可用的模型逻辑。
改为资源处理管道
开发 4.0 版本时,我们的资源导入管道在内部做了一些重要更改,以提高性能、内存使用率和确定性。在大多数情况下,这些更改对用户并无影响,但一种情况除外:资源中的对象不持续到导入管道的最终端,任何先前导入的资源版本将被完全替代。
第一部分的意思是,在后置处理过程中用户无法获得资源中对象的正确引用,第二部分的意思是如果使用先前导入版本的资源引用,后置处理过程中如果进行存储修改,那么这些修改会丢失。
因为不持续而丢失的引用示例
思考下面这个小示例:
public class ModelPostprocessor : AssetPostprocessor { public void OnPostprocessModel(GameObject go) { PrefabUtility.CreatePrefab("Prefabs/" + go.name, go); } }
在 Unity 3.5 中,这会创建一个预设,带所有正确的网格引用,因为所有网格已经是持续的。可是,在 Unity 4.0 中并非如此,相同的后置处理程序会创建一个预设,网格的所有引用将丢失,这仅仅是因为 Unity 4.0 还不知道如何在原模型预设中解决对象引用。如需将模式预设 (modelprefab) 正确复制到预设中,应使用 OnPostProcessAllAssets 浏览所有导入的资源,找到模式预设 (modelprefab) 并按照上述方法创建新预设。
先前导入资源的引用被弃用的示例
第二个示例复杂一些,实际上却是我们见过的在 3.5 版本可用而在 4.0 版本中被破坏的使用实例。以下是一个带网格引用的简单 ScriptableObject。
public class Referencer : ScriptableObject { public Mesh myMesh; }
我们使用 ScriptableObject 来创建资源,在模型中引用网格,然后在后置处理程序中获取该引用,赋予其另外一个名称,重新导入模型时的这样做的最终结果是网格名称由后置处理程序确定。
public class Postprocess : AssetPostprocessor { public void OnPostprocessModel(GameObject go) { Referencer myRef = (Referencer)AssetDatabase.LoadAssetAtPath("Assets/MyRef.asset", typeof(Referencer)); myRef.myMesh.name = "AwesomeMesh"; } }
这在 Unity 3.5 中是可以的,但在 Unity 4.0 中,已导入的模型会被完全替代,因而更改先前导入的网格的名称将没有影响。这里给出的解决方案是通过其他方式找到网格并更改其名称。最重要的是,在 Unity 4.0 中应只更改对后置处理程序的给定输入,不依赖先前导入的相同资源版本。
网格读取/写入 (Read/Write) 选项
Unity 4.0 在网格 (Mesh) 导入设置中增添了“读取/写入已启用 (Read/Write Enabled)” 选项。关闭该选项能节省内存,因为 Unity 可在游戏中卸载网格数据的副本。
可是,如果在运行时以非统一缩放对网格进行缩放或实例化,则必须在其导入设置中启用“读取/写入已启用 (Read/Write Enabled)”。这是因为非统一缩放要求将网格数据保存在内存中。一般来说构建时会检测到这点,但运行时如果网格被缩放或实例化,就必须手动设置该选项。否则将不会在游戏构建中正确呈现。
网格优化
Unity 4.0 中的模型导入器 (Model Importer) 在网格优化方面做得越来越好。Unity 4.0 中模型导入器 (Model Importer) 内的“网格优化 (Mesh Optimization)”复选框现已默认启用,将在网格 (Mesh) 中对顶点重新排序,以获得最佳性能。工程中可能有一些后置处理代码或效果依赖网格的顶点顺序,更改之后可能会破坏这些代码和效果。如果出现这种情况,请关闭网格 (Mesh) 导入器中的“网格优化 (Mesh Optimization)” 选项。特别是使用 SkinnedCloth 组件时,网格优化会导致顶点权重贴图变化。因而,如果在从 3.5 版本中导入的工程中使用 SkinnedCloth,就需要关闭“网格优化 (Mesh Optimization)” 来影响网格或重新配置顶点权重,来匹配新的顶点顺序。
移动输入
对于 Unity 4.0 移动传感器,在平台之间输入,对齐更佳,也就是说只需写入较少代码就可以在移动平台上处理典型输入。现在,加速和陀螺输入将按照屏幕方向进行,iOS 和安卓 (Android) 平台的方法都相同。为了利用该更改,应在处理加速和陀螺输入时重构输入代码并移除平台和屏幕方向特定代码。在 iOS 中,将 Input.compensateSensors 设置为 false 仍可获得旧行为。
,