После обширного эксперимента я смог получить это. Это покрывает все компоненты Unity. Просто сделал это методом расширения, чтобы облегчить жизнь.
public static class ExtensionMethod
{
public static Component AddComponentExt(this GameObject obj, string scriptName)
{
Component cmpnt = null;
for (int i = 0; i < 10; i++)
{
//If call is null, make another call
cmpnt = _AddComponentExt(obj, scriptName, i);
//Exit if we are successful
if (cmpnt != null)
{
break;
}
}
//If still null then let user know an exception
if (cmpnt == null)
{
Debug.LogError("Failed to Add Component");
return null;
}
return cmpnt;
}
private static Component _AddComponentExt(GameObject obj, string className, int trials)
{
//Any script created by user(you)
const string userMadeScript = "Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
//Any script/component that comes with Unity such as "Rigidbody"
const string builtInScript = "UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
//Any script/component that comes with Unity such as "Image"
const string builtInScriptUI = "UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
//Any script/component that comes with Unity such as "Networking"
const string builtInScriptNetwork = "UnityEngine.Networking, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
//Any script/component that comes with Unity such as "AnalyticsTracker"
const string builtInScriptAnalytics = "UnityEngine.Analytics, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
//Any script/component that comes with Unity such as "AnalyticsTracker"
const string builtInScriptHoloLens = "UnityEngine.HoloLens, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
Assembly asm = null;
try
{
//Decide if to get user script or built-in component
switch (trials)
{
case 0:
asm = Assembly.Load(userMadeScript);
break;
case 1:
//Get UnityEngine.Component Typical component format
className = "UnityEngine." + className;
asm = Assembly.Load(builtInScript);
break;
case 2:
//Get UnityEngine.Component UI format
className = "UnityEngine.UI." + className;
asm = Assembly.Load(builtInScriptUI);
break;
case 3:
//Get UnityEngine.Component Video format
className = "UnityEngine.Video." + className;
asm = Assembly.Load(builtInScript);
break;
case 4:
//Get UnityEngine.Component Networking format
className = "UnityEngine.Networking." + className;
asm = Assembly.Load(builtInScriptNetwork);
break;
case 5:
//Get UnityEngine.Component Analytics format
className = "UnityEngine.Analytics." + className;
asm = Assembly.Load(builtInScriptAnalytics);
break;
case 6:
//Get UnityEngine.Component EventSystems format
className = "UnityEngine.EventSystems." + className;
asm = Assembly.Load(builtInScriptUI);
break;
case 7:
//Get UnityEngine.Component Audio format
className = "UnityEngine.Audio." + className;
asm = Assembly.Load(builtInScriptHoloLens);
break;
case 8:
//Get UnityEngine.Component SpatialMapping format
className = "UnityEngine.VR.WSA." + className;
asm = Assembly.Load(builtInScriptHoloLens);
break;
case 9:
//Get UnityEngine.Component AI format
className = "UnityEngine.AI." + className;
asm = Assembly.Load(builtInScript);
break;
}
}
catch (Exception e)
{
//Debug.Log("Failed to Load Assembly" + e.Message);
}
//Return if Assembly is null
if (asm == null)
{
return null;
}
//Get type then return if it is null
Type type = asm.GetType(className);
if (type == null)
return null;
//Finally Add component since nothing is null
Component cmpnt = obj.AddComponent(type);
return cmpnt;
}
}
Использование:
gameObject.AddComponentExt("YourScriptOrComponentName");
Важно понять, как я сделал это так, что вы можете добавить поддержку новых компонентов в любых будущих обновлениях Unity.
Для любого сценария, созданного пользователями:
.find, что нужно, чтобы быть в ??? в функции Assembly.Load
.
Assembly asm = Assembly.Load("???");
Вы можете сделать это, помещая это в скрипте:
Debug.Log("Info: " + this.GetType().Assembly);
я получил: Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Теперь мы должны заменить ??? с этим.
Assembly asm = Assembly.Load("Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
.find, что должно быть в ??? в функции asm.GetType
.
Assembly asm = Assembly.Load("Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType(???);
В данном случае, это просто название скрипта, который вы хотите добавить в GameObject.
Допустим, что ваше имя скрипта NathanScript
:
Assembly asm = Assembly.Load("Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType("NathanScript");
gameObject.AddComponent(type);
Для Unity построен в скриптах/компонентов сценариев не созданных пользователями:
Пример этого является Rigidbody
, Linerenderer
, Image
компонентов. Просто любой компонент, не созданный пользователем.
. Отметить, что должно быть в ??? в функции Assembly.Load
.
Assembly asm = Assembly.Load("???");
Вы можете сделать это, помещая это в скрипте:
ParticleSystem pt = gameObject.AddComponent<ParticleSystem>();
Debug.Log("Info11: " + pt.GetType().Assembly);
я получил: UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Теперь мы должны заменить ??? с этим.
Assembly asm = Assembly.Load("UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
.find, что должно быть в ??? в функции asm.GetType
.
Assembly asm = Assembly.Load("UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType(???);
Вы можете сделать это, помещая это в скрипте:
ParticleSystem pt = gameObject.AddComponent<ParticleSystem>();
Debug.Log("Info: " + pt.GetType());
я получил: UnityEngine.ParticleSystem
Помните, что ParticleSystem
используется здесь в качестве примера. Таким образом, окончательный строка, которая будет идти к функции asm.GetType
будет рассчитываться следующим образом:
string typeString = "UnityEngine." + componentName;
Допустим, что компонент вы хотите добавить это LineRenderer
:
Assembly asm = Assembly.Load("UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
string typeString = "UnityEngine." + "LineRenderer";
Type type = asm.GetType(typeString);
gameObject.AddComponent(type);
Собираем вместе в способе расширения:
Как вы можете видеть, добавление скриптов, которые вы создали, и скрипт/компонент ents, которые поставляются с Unity, требует совершенно другого процесса. Вы можете исправить это, проверив тип, если null
. Если тип null
, выполните другой шаг. Если другой шаг равен null
, то скрипт просто делает не выход.
Что именно не работает? Поиск скрипта, прикрепление его к игровому объекту или к тому и другому? Что происходит при выполнении кода? –
Прикрепление к игровому объекту - проблема здесь, две строки внутри GUILayout.Button. Чтобы найти, я использую DirectoryInfo (на самом деле проверить, существует ли он). Я добавлю систему поиска, которую я использую в код выше. –
Чтобы узнать, существует ли тип, вы можете просто выполнить 'assembly.GetTypes(). Любой (t => t.Name == scriptname);' –