Unity如何通过脚本将运行时GameObject发送至其他编辑器生成AssetBundle?
实现方法
要实现点击应用内按钮将GameObject传递到另一个Unity编辑器并生成AssetBundle,核心思路是序列化GameObject数据→通过命令行参数传递给BatchMode启动的Unity→在编辑器中重建对象并打包,具体步骤如下:
1. 运行时:序列化GameObject并启动BatchMode进程
在你的运行时项目中,给按钮绑定点击事件,将目标GameObject的关键数据序列化为临时文件,然后通过命令行启动另一个Unity编辑器的BatchMode实例,传递临时文件路径和AssetBundle输出路径。
示例代码:
using UnityEngine; using System.IO; using System.Diagnostics; public class ExportToAssetBundle : MonoBehaviour { public GameObject targetGameObject; // 要导出的目标对象 public string unityEditorPath = @"C:\Program Files\Unity\Hub\Editor\2022.3.1f1\Editor\Unity.exe"; public string assetBundleOutputPath = @"D:\MyAssetBundles\my_bundle"; public void OnExportButtonClick() { // 1. 序列化GameObject数据到临时JSON文件 string tempJsonPath = Path.Combine(Application.temporaryCachePath, "exported_obj_data.json"); ObjectExportData exportData = new ObjectExportData(targetGameObject); string jsonData = JsonUtility.ToJson(exportData); File.WriteAllText(tempJsonPath, jsonData); // 2. 构造BatchMode命令行参数 // -batchmode: 后台运行Unity // -quit: 任务完成后自动退出 // -executeMethod: 指定要执行的静态方法 string commandArgs = $"-batchmode -quit -executeMethod AssetBundleBuilder.BuildFromExportData \"{tempJsonPath}\" \"{assetBundleOutputPath}\""; // 3. 启动Unity编辑器进程 Process.Start(new ProcessStartInfo(unityEditorPath, commandArgs) { UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true }); } } // 自定义序列化类,存储GameObject的必要信息(按需扩展) [System.Serializable] public class ObjectExportData { public Vector3 position; public Quaternion rotation; public Vector3 localScale; public string prefabResourcePath; // 如果对象基于预制体,存储预制体在编辑器项目中的路径 public ObjectExportData(GameObject obj) { position = obj.transform.position; rotation = obj.transform.rotation; localScale = obj.transform.localScale; // 这里可以扩展存储组件、材质引用等信息,比如Mesh数据、材质路径等 } }
2. 编辑器端:实现BatchMode执行的打包逻辑
在用于生成AssetBundle的Unity编辑器项目中,创建一个静态工具类,实现从临时文件读取数据、重建GameObject、生成AssetBundle的逻辑。
示例代码:
using UnityEditor; using UnityEngine; using System.IO; public static class AssetBundleBuilder { // 这个方法会被BatchMode调用,参数来自命令行 public static void BuildFromExportData(string inputJsonPath, string outputPath) { // 1. 读取并反序列化数据 string jsonContent = File.ReadAllText(inputJsonPath); ObjectExportData exportData = JsonUtility.FromJson<ObjectExportData>(jsonContent); // 2. 重建GameObject GameObject targetObj; if (!string.IsNullOrEmpty(exportData.prefabResourcePath)) { // 如果是基于预制体,直接加载并实例化 targetObj = AssetDatabase.LoadAssetAtPath<GameObject>(exportData.prefabResourcePath); targetObj = Object.Instantiate(targetObj); } else { // 动态创建对象并设置属性 targetObj = new GameObject("Exported_Object"); targetObj.transform.position = exportData.position; targetObj.transform.rotation = exportData.rotation; targetObj.transform.localScale = exportData.localScale; // 按需添加组件、设置材质等,比如读取序列化的Mesh数据添加MeshFilter } // 3. 将对象保存为预制体(AssetBundle需要基于AssetDatabase中的资源) string tempAssetDir = "Assets/TempExportAssets"; if (!Directory.Exists(tempAssetDir)) { Directory.CreateDirectory(tempAssetDir); } string tempPrefabPath = Path.Combine(tempAssetDir, "ExportedPrefab.prefab"); PrefabUtility.SaveAsPrefabAsset(targetObj, tempPrefabPath); // 4. 刷新AssetDatabase并设置AssetBundle标签 AssetDatabase.Refresh(); AssetImporter importer = AssetImporter.GetAtPath(tempPrefabPath); importer.SetAssetBundleNameAndVariant("custom_bundle", ""); // 5. 构建AssetBundle BuildPipeline.BuildAssetBundles(Path.GetDirectoryName(outputPath), BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); // 6. 清理临时文件 AssetDatabase.DeleteAsset(tempAssetDir); File.Delete(inputJsonPath); // 退出编辑器 EditorApplication.Exit(0); } } // 注意:这个类要和运行时的ObjectExportData完全一致 [System.Serializable] public class ObjectExportData { public Vector3 position; public Quaternion rotation; public Vector3 localScale; public string prefabResourcePath; }
3. 关键注意事项
- 序列化一致性:运行时和编辑器项目中的
ObjectExportData类定义必须完全相同,否则会出现反序列化失败。 - 资源依赖:如果GameObject包含自定义脚本、材质、纹理等资源,编辑器项目中必须存在这些资源,或者在序列化时存储资源的GUID/相对路径,确保编辑器能正确加载。
- 路径配置:Unity编辑器的路径要根据你的安装版本和系统调整(Mac系统路径类似
/Applications/Unity/Hub/Editor/2022.3.1f1/Unity.app/Contents/MacOS/Unity)。 - 权限问题:确保运行时应用有写入临时目录的权限,编辑器进程有写入AssetBundle输出路径的权限。
- 扩展序列化逻辑:如果需要导出复杂对象,比如带动画、粒子系统的GameObject,需要扩展
ObjectExportData,序列化更多组件数据,在编辑器端重建对应组件。
内容的提问来源于stack exchange,提问作者zakilman
相关产品推荐
相关产品推荐

