包含此页的版本:
不含此页的版本:
两个单声道Unity 中使用的脚本后端。更多信息
请参阅术语表和IL2CPP Unity 开发的脚本后端,在为某些平台构建项目时,可以将其用作 Mono 的替代方案。更多信息
请参阅术语表 脚本后端为Unity中的脚本提供支持的框架。Unity 支持三种不同的脚本后端,具体取决于目标平台:Mono、.NET 和 IL2CPP。但是,通用 Windows 平台仅支持两个:.NET 和 IL2CPP。更多信息
请参阅术语表内部缓存所有 C#System.Reflection对象,Unity 不会对它们进行垃圾回收。这意味着垃圾回收器在应用程序的生存期内会持续扫描缓存的 C# 反射对象,这会导致不必要且可能巨大的垃圾回收器开销。
若要最大程度地减少垃圾回收器开销,请避免使用在运行时创建大量 C# 反射对象的方法,例如Assembly.GetTypes和Type.GetMethods.相反,在 Unity 编辑器中扫描程序集以查找所需的数据并将其序列化,或者使用代码生成使数据在运行时可用。
以下示例演示如何在编辑器中扫描程序集、序列化数据,并在运行时使用它而不进行反射。假设您要查找实现名为IMyFeature并在运行时使用该信息。您可以编写一个编辑器脚本来扫描实现的所有类型IMyFeature并将其名称保存到ScriptableObject或 JSON 文件,如下所示:
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
[CreateAssetMenu(menuName = "Feature/FeatureTypeList")]
public class FeatureTypeList : ScriptableObject
{
public List<string> typeNames;
}
public static class FeatureTypeScanner
{
[MenuItem("Tools/Scan IMyFeature Types")]
public static void ScanTypes()
{
var featureType = typeof(IMyFeature);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => featureType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
.Select(t => t.FullName)
.ToList();
// Create/overwrite the asset
var asset = ScriptableObject.CreateInstance<FeatureTypeList>();
asset.typeNames = types;
AssetDatabase.CreateAsset(asset, "Assets/FeatureTypeList.asset");
AssetDatabase.SaveAssets();
Debug.Log($"Found {types.Count} types implementing IMyFeature. Saved to FeatureTypeList.asset");
}
}
从菜单中运行工具>扫描 IMyFeature 类型。这将创建Assets/FeatureTypeList.asset包含类型名称列表。
在运行时,你可以加载此资产,并通过以下方式使用类型名称进行实例化Activator.CreateInstance,或仅用于展示。如果使用 codegen,则不需要反射,如下所示:
public class FeatureTypeLoader : MonoBehaviour
{
public FeatureTypeList featureTypes;
void Start()
{
var assemblyName = this.GetType().Assembly.FullName;
foreach (var typeName in featureTypes.typeNames)
{
Debug.Log("Instantiating feature type: " + typeName);
Activator.CreateInstance(assemblyName, typeName);
// You can also use Type.GetType(typeName) (both of these still uses reflection but only on the pre-selected feature types instead of casting a wider net across all sort of types in the assembly.)
}
}
}
您可以在编辑器时生成一个包含类型或委托静态数组的 C# 文件,而不是存储类型名称,从而消除所有运行时反射。以下代码示例生成一个文件Assets/GeneratedFeatureTypes.cs使用已发现类型的静态数组,您可以在运行时使用该数组,而无需反射:
using UnityEditor;
using System;
using System.Linq;
using System.Text;
using System.IO;
public static class FeatureTypeCodeGen
{
[MenuItem("Tools/CodeGen IMyFeature Types")]
public static void CodeGenTypes()
{
var featureType = typeof(IMyFeature);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => featureType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
.ToList();
StringBuilder sb = new StringBuilder();
sb.AppendLine("public static class GeneratedFeatureTypes {");
sb.AppendLine(" public static readonly System.Type[] Types = new System.Type[] {");
foreach (var t in types)
{
sb.AppendLine($" typeof({t.FullName}),");
}
sb.AppendLine(" };");
sb.AppendLine("}");
File.WriteAllText("Assets/GeneratedFeatureTypes.cs", sb.ToString());
AssetDatabase.Refresh();
Debug.Log("Generated FeatureTypes.cs with " + types.Count + " types.");
}
}