Nat*_*ann 3 c# unity-game-engine unity5
我目前正在为 Unity 编辑器(自定义检查器和自定义窗口)制作一个系统,该系统将自动化并使我们正在制作的游戏的美术师的工作更容易,但我遇到了障碍。
我试图找到一种方法,通过编辑器文本字段输入和 GUI 按钮动态添加未知脚本到场景中的游戏对象。艺术家/程序员将在文本字段中键入脚本的名称,它将搜索并添加到游戏对象中,但我不知道如何进行此操作,特别gameObject.AddComponent()是因为 Unity 5.3 中的某些功能已被弃用
这是我尝试做的:
public string scriptname;
GameObject obj = null;
scriptname = EditorGUILayout.TextField("Script name:", scriptname, GUILayout.MaxHeight(25));
if (GUILayout.Button("Attach script"))
{
//search for the script to check if it exists, using DirectoryInfo
DirectoryInfo dir = new DirectoryInfo(Application.dataPath);
FileInfo[] info = dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo f in info) // cycles through all the files
{
if(f.Name == scriptname)
{
//attaches to the gameobject (NOT WORKING)
System.Type MyScriptType = System.Type.GetType(scriptname + ",Assembly-CSharp");
obj.AddComponent(MyScriptType);
}
}
}
Run Code Online (Sandbox Code Playgroud)
(当然,这是一个总结版,我从脚本的不同部分复制了相关的行)。
但它不起作用。有任何想法吗?
经过广泛的实验,我得到了这个。这也涵盖了所有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;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
gameObject.AddComponentExt("YourScriptOrComponentName");
Run Code Online (Sandbox Code Playgroud)
了解我是如何做到的很重要,这样您就可以在任何未来的 Unity 更新中添加对新组件的支持。
对于用户创建的任何脚本:
1.找出需要在??? 在Assembly.Load函数中。
Assembly asm = Assembly.Load("???");
Run Code Online (Sandbox Code Playgroud)
你可以通过把它放在你的脚本中来做到这一点:
Debug.Log("Info: " + this.GetType().Assembly);
Run Code Online (Sandbox Code Playgroud)
我有: 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");
Run Code Online (Sandbox Code Playgroud)
2.找出需要在??? 在asm.GetType函数中。
Assembly asm = Assembly.Load("Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType(???);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它只是您要添加到游戏对象的脚本的名称。
假设您的脚本名称是NathanScript:
Assembly asm = Assembly.Load("Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType("NathanScript");
gameObject.AddComponent(type);
Run Code Online (Sandbox Code Playgroud)
对于非用户创建的 Unity 内置脚本/组件脚本:
这方面的例子是Rigidbody, Linerenderer,Image组件。只是任何不是由用户创建的组件。
1.找出需要在??? 在Assembly.Load函数中。
Assembly asm = Assembly.Load("???");
Run Code Online (Sandbox Code Playgroud)
你可以通过把它放在你的脚本中来做到这一点:
ParticleSystem pt = gameObject.AddComponent<ParticleSystem>();
Debug.Log("Info11: " + pt.GetType().Assembly);
Run Code Online (Sandbox Code Playgroud)
我有: UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
我们现在应该更换???接着就,随即。
Assembly asm = Assembly.Load("UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Run Code Online (Sandbox Code Playgroud)
2.找出需要在??? 在asm.GetType函数中。
Assembly asm = Assembly.Load("UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
Type type = asm.GetType(???);
Run Code Online (Sandbox Code Playgroud)
你可以通过把它放在你的脚本中来做到这一点:
ParticleSystem pt = gameObject.AddComponent<ParticleSystem>();
Debug.Log("Info: " + pt.GetType());
Run Code Online (Sandbox Code Playgroud)
我有: UnityEngine.ParticleSystem
请记住,ParticleSystem这里用作示例。因此,将进入该asm.GetType函数的最终字符串将按如下方式计算:
string typeString = "UnityEngine." + componentName;
Run Code Online (Sandbox Code Playgroud)
假设您要添加的组件是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);
Run Code Online (Sandbox Code Playgroud)
将它放在一个扩展方法中:
如您所见,添加您创建的脚本和 Unity 附带的脚本/组件需要完全不同的过程。您可以通过检查类型 if 来解决此问题null。如果类型为null,则执行其他步骤。如果其他步骤是null太那么脚本根本就没有退出。
| 归档时间: |
|
| 查看次数: |
4854 次 |
| 最近记录: |