/// <summary> /// 导出 /// </summary> static public void Export(SceneTree[] trees, List <MeshCollider> meshColliders, bool exportRes, bool compress) { // 收集依赖 var sb = new StringBuilder(); int depsCount = 0; var resCollector = new ResDescCollector(); var dictRes = new Dictionary <string, ResExportDesc>(); // 光照图(不能卸载第一张光照图,否则unity_Lightmap_HDR会置为1) var lightMaps = LightmapSettings.lightmaps; if (null != lightMaps && lightMaps.Length > 0 && null != lightMaps[0].lightmapColor) { var resName = ResDepBase.GetResName(lightMaps[0].lightmapColor); resCollector.AddLightMap(resName, 0, true); } // 场景 for (int i = 0; i < trees.Length; ++i) { var tree = trees[i]; if (null != tree && tree.settings.objType == SceneTreeObjType.Renderer) { var n = tree.CollectDeps(dictRes); sb.AppendFormat("Tree {0} deps count is {1}\n", tree.settings.name, n); depsCount += n; } } sb.AppendFormat("All tree deps count is {0}\n", depsCount); Debug.Log(sb.ToString()); // 生成节点数据 var prefabCollection = new ScenePrefabCollection(); var treeDatas = new List <SceneTreeData>(); for (int i = 0; i < trees.Length; ++i) { var tree = trees[i]; if (null != tree) { var data = tree.BuildData(prefabCollection, dictRes); treeDatas.Add(data); } } // LightMap这里要置空一下,仅清空LightmapSettings.lightmaps仍然有依赖 Lightmapping.lightingDataAsset = null; // 只留一盏主光源 var lights = Light.GetLights(LightType.Directional, 0); Light mainLight = null; if (lights.Length > 0) { mainLight = lights[0]; for (int i = 1; i < lights.Length; ++i) { GameObject.DestroyImmediate(lights[i].gameObject); } } // MeshCollider var deps = new List <ResDepBase>(); ResDepBase.CollectColliderDependencies(meshColliders, deps); for (int n = 0, cn = deps.Count; n < cn; ++n) { var dep = deps[n]; dep.CollectRes(resCollector, dictRes); dep.RemoveDependencies(); } // 场景描述 var goSceneDesc = new GameObject("scene_desc"); SceneDesc desc = goSceneDesc.AddComponent <SceneDesc>(); desc.mainLight = mainLight; desc.lightMapCount = LightmapSettings.lightmaps.Length; desc.resCollection = resCollector.Export(); desc.trees = treeDatas.ToArray(); desc.prefabs = prefabCollection.Export(); // 移除编辑脚本 var cfgs = UnityEngine.Object.FindObjectsOfType <EditorSceneObject>(); for (int i = 0; i < cfgs.Length; ++i) { UnityEngine.Object.DestroyImmediate(cfgs[i]); } // 资源 if (exportRes) { var sbExport = new StringBuilder(); sbExport.AppendFormat("Resources Count[{0}]\n", dictRes.Count); sbExport.Append("---------------------------------------------------------------\n"); foreach (var pair in dictRes) { var resDesc = pair.Value; ResExportUtil.ExportRes(resDesc, compress); sbExport.AppendFormat("{0}/{1} - {2}\n", resDesc.resDir, resDesc.resName, resDesc.refCount); } sbExport.Append("---------------------------------------------------------------\n"); Debug.Log(sbExport.ToString()); } }
/// <summary> /// 生成数据 /// </summary> public SceneTreeData BuildData(ScenePrefabCollection prefabCollection, Dictionary <string, ResExportDesc> dictRes) { var childrenList = new List <int>(); var nodeDatas = new List <SceneTreeNodeData>(); var data = new SceneTreeData(); data.name = _settings.name; data.splitType = _settings.splitType; data.objType = _settings.objType; data.Index = _settings.Index; data.viewDistance = _settings.viewDistance; data.maxItemBoundsSize = _settings.maxItemBoundsSize; var id = 0; VisitNodes(node => node.id = id++); // 生成数据 int n = 0; int nodeCount = id; VisitNodes(node => { EditorUtility.DisplayProgressBar(string.Format("Build data({0}/{1})", n + 1, nodeCount), node.id.ToString(), (float)(n + 1) / nodeCount); // 收集资源 node.CollectRes(dictRes); childrenList.Clear(); var children = node.children; if (null != children) { for (int j = 0; j < children.Length; ++j) { var child = children[j]; if (null == child) { continue; } childrenList.Add(child.id); } } // 数据 var nodeData = new SceneTreeNodeData(); nodeData.id = node.id; nodeData.bounds = node.bounds; if (_settings.objType == SceneTreeObjType.Collider) { nodeData.colliders = node.ExportColliders(); } else { node.ExportObjects(data, nodeData, prefabCollection); } nodeData.children = childrenList.ToArray(); nodeDatas.Add(nodeData); ++n; }); EditorUtility.ClearProgressBar(); data.nodes = nodeDatas.ToArray(); return(data); }
/// <summary> /// 导出对象 /// </summary> public void ExportObjects(SceneTreeData treeData, SceneTreeNodeData nodeData, ScenePrefabCollection prefabCollection) { var objs = new List <SceneTreeNodeObjectData>(); var instances = new List <SceneObjectInstanceData>(); for (int i = 0; i < _items.Length; ++i) { var item = _items[i]; var obj = new SceneTreeNodeObjectData(); obj.go = item.go; obj.trans = item.go.transform; obj.bounds = item.bounds; obj.go.layer = LayerDefine.Invisible; obj.lods = new SceneTreeNodeObjectLodData[item.resDep.lods.Count]; for (int n = 0; n < obj.lods.Length; ++n) { var lod = item.resDep.lods[n]; var renderer = lod.go.GetComponent <Renderer>(); if (null == renderer) { Debug.LogErrorFormat("Null renderer of {0} lod {1}!", item.go.name, n); continue; } var lodData = new SceneTreeNodeObjectLodData(); lodData.resCollection = lod.resCollector.Export(); // Cfg if (null != item.cfg) { if (null != item.cfg.lods && n > 0 && n <= item.cfg.lods.Length) { var lodCfg = item.cfg.lods[n - 1]; lodData.viewDist = lodCfg.viewDist; lodData.isBillboard = lodCfg.isBillboard; } } lodData.mats = renderer.sharedMaterials; obj.lods[n] = lodData; if (0 == n) { obj.renderer = renderer; renderer.enabled = false; } } // 无效对象 if (null == obj.renderer) { continue; } // 显示配置 if (null != item.cfg) { if (item.cfg.usePrefab) { if ((item.objTypeFlag & (1 << (int)SceneTreeObjType.Collider)) != 0) { Debug.LogErrorFormat("Item {0} has collider, can not use prefab!", item.go.name); } else { var prefabId = prefabCollection.AddPrefab(obj); if (prefabId >= 0) { var instance = new SceneObjectInstanceData { prefabId = prefabId, }; instances.Add(instance); // 销毁对象 //if (prefabCollection.GetRefCount(prefabId) > 1) //{ // GameObject.DestroyImmediate(obj.go); // obj.go = null; //} } } } } objs.Add(obj); } nodeData.objects = objs.ToArray(); nodeData.instances = instances.ToArray(); }