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中所述實現,並帶有額外的日誌記錄,以向開發人員提供有關如何用生產質量的東西替換該調用的提示。 您可以在下面看到此類日誌的屏幕截圖:

Log when game enter in play mode

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.

由於平臺限制(此方法使用的方法/類型並非在所有平臺上均受支持)以及對玩家的性能影響,因此該方法被標記爲過時,並且在嘗試構建遊戲時會出現錯誤,這意味着您確實需要採取一些措施使您的代碼可以投入生產。

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