addcomponent_AddComponent(string):Unity 5.0中的API删除

addcomponent_AddComponent(string):Unity 5.0中的API删除

addcomponent

GameObject :: AddComponent(string) 已在Unity 5.0中删除。 备选方案是此API的两个重载,一个重载了组件类型作为泛型类型参数,另一个重载了对组件类型的引用。 已配置自动API更新,但并非所有情况都可以自动处理。 (GameObject::AddComponent(string) has been removed in Unity 5.0.  The alternatives are two overloads of this API, one taking the component type as a generic type argument and another one taking a reference to the component type. Automatic API updating has been configured but not all cases can be handled automatically.)

In our quest to improve Unity we realized that we should let GameObject::AddComponent(string) go; in our first attempt we were too “aggressive” and removed GetComponent(string) as well. However, after receiving some great feedback, we reevaluated this decision and reintroduced it.

在寻求改进Unity的过程中,我们意识到应该放开GameObject :: AddComponent(string) ; 在我们的第一次尝试中,我们过于“激进”,并删除了GetComponent(string) 。 但是,在收到一些好评后,我们重新评估了该决定并重新提出。

Unfortunately we could not do the same with AddComponent(string) (it would reintroduce the very same dependencies we are aiming to break, i.e, from core to subsystems). If your project uses this method you have two possible alternatives (depending on the accessibility of the type as explained in the rules related to compilation order and how the type name is specified). We’ll further describe these options in the following paragraphs (examples are written in C# but the same concepts applies to UnityScript (js) / Boo).

不幸的是,我们不能对AddComponent(string)做同样的事情(它将重新引入我们要打破的完全相同的依赖关系,即从核心到子系统)。 如果您的项目使用此方法,则有两种可能的选择(取决于 与编译顺序相关规则 中所述的类型的可访问性 以及如何指定类型名称)。 我们将在以下段落中进一步描述这些选项(示例使用C#编写,但相同的概念适用于UnityScript(js)/ Boo)。

方案1:将要添加的类型的名称作为常量/字符串文字传递,并且在构建时就知道该类型 (Scenario 1: Name of the type being added is passed as a constant / string literal and the type is known at build time)

This scenario is straightforward and easily identifiable: AddComponent() is called with a constant string and you are able to declare local variables (or parameters, or fields) of the type being added. In this case you can simply use the generic version of AddComponent(), as shown in the following example:

这种情况很简单,也很容易识别:用常量字符串调用AddComponent(),并且您可以声明要添加的类型的局部变量(或参数或字段)。 在这种情况下,您可以简单地使用AddComponent()的通用版本,如以下示例所示:

[csharp] // each class declared in its own file namespace N1 { class C1 : MonoBehaviour { } }

[csharp] //在其自己的文件命名空间N1中声明的每个类{class C1:MonoBehaviour {}}

class C2 : MonoBehaviour { }

C2类:MonoBehaviour {}

class MyObj : MonoBehaviour { public void Start() { AddComponent(“C1”); // only the class name, no namespace information…. AddComponent(“C2”); } } [/csharp]

类MyObj:MonoBehaviour {public void Start(){AddComponent(“ C1”); //仅是类名,没有名称空间信息…。 AddComponent(“ C2”); } [/ csharp]

should be changed to:

应该更改为:

[csharp] // C1 / C2 declared as before.

[csharp] //之前声明的C1 / C2。

class MyObj : MonoBehaviour { public void Start() { AddComponent< N1.C1>(); AddComponent< C2>(); } } [/csharp]

类MyObj:MonoBehaviour {public void Start(){AddComponent <N1.C1>(); AddComponent <C2>(); } [/ csharp]

when porting the project to Unity 5.0.

将项目移植到Unity 5.0时。

Note that classes declared inside namespaces (C1) will require the namespace to be specified (line 8). This is unlike the version of this API that used to take a string, it only expects the class name).

请注意,在名称空间(C1)中声明的类将需要指定名称空间(第8行)。 这与该API的用于接收字符串的版本不同,它仅需要类名。

方案2:参数/字段/局部变量作为参数传递给AddComponent。 (Scenario 2: Parameter  / field / local variables are passed as the argument to AddComponent.)

This scenario is also easily identifiable by simply checking the call to AddComponent() (it will use a field / local variable / parameter as the argument). Unfortunately, in this case the alternative is to rely on Type.GetType(string) to retrieve a reference to the type at runtime and call AddComponent(type) – which comes with some drawbacks:

通过简单地检查对AddComponent()的调用,也可以很容易地识别这种情况(它将使用字段/局部变量/参数作为参数)。 不幸的是,在这种情况下,替代方法是依靠Type.GetType(string)在运行时检索对该类型的引用并调用AddComponent(type) –这有一些缺点:

  1. Scenarios involving  AOT / stripping The same constraints that apply to platforms apply here. For instance, the AOT compiler may not include a type in the final binary if no reference to that type exists in the code (i.e, only the type name, as a string, is used). Also, keep in mind that on IL2CPP backend, stripping is always enabled.

    涉及AOT /剥离的场景这里适用于平台的相同约束。 例如,如果代码中不存在对该类型的引用,则AOT编译器可能不将其包含在最终二进制文件中(即,仅使用类型名作为字符串)。 另外,请记住,在IL2CPP后端上,始终启用剥离。

  2. Requires the type’s assembly fully qualified name This is more an annoyance than an issue, nevertheless, assembly qualified names can be pretty big, intimidating and prone to syntax errors.

    需要类型的程序集完全限定名称这比问题更令人烦恼,但是,程序集限定名称可能很大,令人生畏并且容易出现语法错误。

  3. Requires an actual .Net type to exist Some Unity components only existed in native code (i.e, no .Net counterpart) (for instance, EllipsoidParticleEmitter). We added .Net representation for such components (from UnityEngine) but we may always have overlooked one or more types ;)

    需要存在实际的.Net类型。某些Unity组件仅以本机代码存在(即,没有.Net对应项)(例如EllipsoidParticleEmitter)。 我们为此类组件添加了.Net表示(来自UnityEngine),但我们可能始终忽略了一种或多种类型;)

  4. Performance overhead involved in type lookup and / or other tasks. Usually this should not be an issue unless Type.GetType(string) gets called in a tight loop, nevertheless, you should keep it in mind.

    类型查找和/或其他任务涉及的性能开销。 通常,除非在紧密循环中调用Type.GetType(string),否则这应该不是问题,但是,请记住这一点。

自动API更新 (Automatic API Updating)

Since we want to make project updates as easy as possible, we configured our API Updater to take this change into account. When calls to AddComponent(string) are found, the updater analyzes the value used as the argument and, if it succeeds in resolving the type (which excludes the cases described by scenario 2 as the type name is only known at runtime) it simply applies the mechanics described in scenario 1 replacing the call to AddComponent(string) with a call to:

由于我们希望使项目更新尽可能容易,因此我们配置了API Updater来考虑此更改。 找到对AddComponent(string)的调用后,更新程序将分析用作参数的值,如果更新程序成功解析了类型(排除方案2所述的情况,因为类型名仅在运行时才知道),则更新程序将简单地应用场景1中描述的机制将对AddComponent(string)的调用替换为对以下内容的调用:

[csharp]AddComponent< T>() // for C#[/csharp]

[csharp] AddComponent <T>()//用于C#[/ csharp]

[js]AddComponent.< T>() // for UnityScript (js) [/js]

[js] AddComponent。<T>()//用于UnityScript(js)[/ js]

and AddComponent[of T]() for boo.

和AddComponent [of T]()为boo。

(“T” being the type of the component being added)

(“ T”是要添加的组件的类型)

While planning how to handle the scenario in which the updater is unable to resolve the type being passed as the argument (scenario 2 and also some sub cases of scenario 1 – classes declared in namespaces for instance), we’ve tried to achieve a balance between usefulness, reliability and ease of use. After our first evaluation we came up with the following options:

在计划如何处理更新程序无法解析作为参数传递的类型的方案时(方案2以及方案1的某些子情况-例如在名称空间中声明的类),我们尝试达到平衡在实用性,可靠性和易用性之间。 经过我们的首次评估,我们提出了以下选择:

  1.  Do not touch the script at all (not good);

    完全不要触摸脚本(不好);
  2. Simply replace all invocations to AddComponent(string) with its generic version (or the one taking System.Type as its parameter) and assume / hope it works;

    只需用其通用版本(或以System.Type作为其参数的版本)替换对AddComponent(string)的所有调用,并假定/希望它可以工作;

  3. Replace such invocations with more elaborate, possibly slow, code that tries to resolve the type at runtime looking in multiple assemblies.

    用更复杂,可能更慢的代码替换这些调用,这些代码试图在运行时查看多个程序集来解析类型。

Option 1 got discarded really quick and option 2 did not look very user friendly / reliable or professional to us, so we’re left with option 3 which, to be fair, didn’t sound like a great solution either. In the end we settled on what we consider to be a good compromise:  calls to AddComponent(string) that fall into this category (type cannot be resolved at compile time because it is passed through non constants / non literals) are replaced by a call to APIUpdaterRuntimeServices::AddComponent(…) which, in the editor, is implemented as described in option 3 with extra logging to provide developers hints on how to replace the call with something that is production quality. Below you can see a screenshot of such a log:

选项1很快就被丢弃了,而选项2看起来对我们来说不是非常用户友好/可靠或专业,所以我们剩下选项3了,公平地说,这也不是一个很好的解决方案。 最后,我们确定了我们认为是一个不错的折衷方案:属于此类的对AddComponent(string)的调用(类型不能在编译时解析,因为它通过非常量/非文字传递)被调用替换到APIUpdaterRuntimeServices :: AddComponent(…),该方法在编辑器中如选项3中所述实现,并带有额外的日志记录,以向开发人员提供有关如何用生产质量的东西替换该调用的提示。 您可以在下面看到此类日志的屏幕截图:

addcomponent_AddComponent(string):Unity 5.0中的API删除

Log when game enter in play mode

当游戏进入播放模式时记录

(note that the line / column displayed in the log may be slightly off due to other updates being applied; also it is worth mentioning that the explanation uses C# generic method syntax – so if your scripts are written in UnityScript/Boo make the appropriate changes).

(请注意,由于应用了其他更新,因此日志中显示的行/列可能会略有偏离;另外,值得一提的是,说明使用的是C#通用方法语法-因此,如果您的脚本是用UnityScript / Boo编写的,请进行适当的更改)。

In the above example, even though the updater was unable to resolve the type, when in play mode, i.e, when using the editor version of UnityEngine assembly, APIUpdaterRuntimeServices::AddComponent() found out that the component being added can in fact be resolved and suggested replacing that call with a call to the generic overload of GameObject::AddComponent().

在上面的示例中,即使更新程序无法解析类型,但在播放模式下(即,在使用UnityEngine程序集的编辑器版本时),APIUpdaterRuntimeServices :: AddComponent()发现实际上可以解析所添加的组件并建议将该调用替换为对GameObject :: AddComponent()的一般重载的调用。

Due to platform constraints (this method uses methods / types not supported on all platforms) and performance implications for players, this method is marked as obsolete and you’ll get an error if you try to build the game, meaning that you do need to take some action to make your code ready for production.

由于平台限制(此方法使用的方法/类型并非在所有平台上均受支持)以及对玩家的性能影响,因此该方法被标记为过时,并且在尝试构建游戏时会出现错误,这意味着您确实需要采取一些措施使您的代码可以投入生产。

addcomponent_AddComponent(string):Unity 5.0中的API删除

While we understand that this is not a perfect solution we do believe that this is a necessary step to untangle this dependency, and we feel that the Unity 5.0 launch is the perfect time to make this change.

尽管我们知道这不是一个完美的解决方案,但我们确实认为这是消除这种依赖性的必要步骤,并且我们认为Unity 5.0的推出是进行此更改的最佳时机。

Was this information useful? Do you have any compliments? comments? complaints? Drop me a message!

这些信息有用吗? 你有什么夸奖吗? 注释? 投诉吗 给我留言!

@adrianoverona

@adrianoverona

翻译自: https://blogs.unity3d.com/2015/01/21/addcomponentstring-api-removal-in-unity-5-0/

addcomponent