public void Load(ISaveable saveable) { if (IsRegistered(saveable)) { string saveString = storage?.GetString(saveable.SaveKey, string.Empty); if (string.IsNullOrEmpty(saveString)) { saveable.LoadDefaults(); } else { try { object save = JsonConvert.DeserializeObject(saveString, saveable.SaveType); saveable.LoadSave(save); } catch (System.Exception exception) { UDebug.LogError(exception.Message); saveable.LoadDefaults(); } } } else { throw new UnityException($"Load: saveable of type => {saveable.GetType().Name} is not registered on ISaveService"); } }
public AssetBundle SyncLoadAssetBundle(string path) { try { #if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_IOS if (DevelopSetting.IsUsePersistent) { path = path.Replace("file:///", ""); } else { path = path.Replace("file://", ""); } #elif UNITY_ANDROID if (DevelopSetting.IsUsePersistent) { path = path.Replace("file:///", ""); } #endif AssetBundle ab = AssetBundle.LoadFromFile(path); return(ab); } catch (System.Exception e) { UDebug.LogError(e.Message); return(null); } }
IEnumerator MyTest(string FileUrl) { float maxNum = 100; for (int i = 0; i < maxNum; i++) { int randomNum = Random.Range(1, 100000); FileUrl = FileUrl + "?v=" + randomNum; WWW www = new WWW(FileUrl); yield return(www); if (string.IsNullOrEmpty(www.error)) { UDebug.Log("WriteFile: loginwindow.ab "); string tempFilePath = PathHelper.PersistentPath + "loginwindow" + i + ".ab"; Util.WriteFile(tempFilePath, www.bytes); } else { UDebug.LogError(string.Format("{0}down failed:{1}", FileUrl, www.error)); yield break; } GameStateManager.Instance.DownProgressChangeEvent(i + 1, maxNum, (float)i / maxNum); yield return(new WaitForSeconds(0.2f)); } }
public Object[] loadAllResource(string path) { Object[] objs = Resources.LoadAll(path); if (objs == null) { UDebug.LogError("resName:" + path + " not found in Resources"); } return(objs); }
public int PackRects(NativeAPI.stbrp_rect[] rects) { var addedCount = 0; var input = new List <NativeAPI.stbrp_rect>(rects); var next = new List <NativeAPI.stbrp_rect>(); while (input.Count > 0) { input.Sort( (l, r) => { if (r.h > l.h) { return(-1); } if (r.h < l.h) { return(1); } return((r.w > l.w) ? -1 : ((r.w < l.w) ? 1 : 0)); } ); while (input.Count > 0) { var last = input.Count - 1; var cur = input[last]; input.RemoveAt(last); var added = false; for (int i = 0; i < m_pagePacker.Count; ++i) { var tp = m_pagePacker[i]; if (tp.Add(cur)) { ++addedCount; added = true; break; } } if (!added) { next.Add(cur); } } if (next.Count > 0) { if (m_pagePacker.Count > MaxPage) { UDebug.LogError("There is too many rects to pack: MaxPage = {0}", MaxPage); break; } var temp = next; next = input; input = temp; m_pagePacker.Add(new _PagePacker()); } } return(addedCount); }
public Object loadResources(string path) { Object obj = Resources.Load(path); if (obj == null) { UDebug.LogError("resName:" + path + " not found in Resources"); } return(obj); }
IEnumerator CheckFileListMd5(VersionConfig serverVersionConfig, FileUpdateVo versionVo) { string content = File.ReadAllText(versionVo.PersistentPath); VersionConfig persistentVersionConfig = JsonUtility.FromJson <VersionConfig>(content); int persistentVersion = persistentVersionConfig.resVersion; int serverVersion = serverVersionConfig.resVersion; if (serverVersion >= persistentVersion) { bool versionConfigChange = false; FileUpdateVo fileListVo = new FileUpdateVo(AppConst.FileListName, versionVo.Url, versionVo.Random, string.Empty, 100); string fileListMd5 = Util.Md5file(fileListVo.PersistentPath); FileCheckResult checkResult = null; byte[] fileListBytes = null; if (!serverVersionConfig.fileListMd5.Equals(fileListMd5)) { versionConfigChange = true; WWW www = new WWW(fileListVo.FileUrl); yield return(www); if (string.IsNullOrEmpty(www.error)) { string[] fileList = www.text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); List <string> serverFileList = new List <string>(fileList); fileList = File.ReadAllLines(fileListVo.PersistentPath); List <string> persistentFileList = new List <string>(fileList); checkResult = Util.GetChangList(persistentFileList, serverFileList); fileListBytes = www.bytes; } else { UDebug.LogError(string.Format("{0}down failed:{1}", fileListVo.FileUrl, www.error)); yield break; } www.Dispose(); //下载云端list } else if (serverVersion > persistentVersion)//只是version改变了,实际资源没有变,或者上次资源下载好了,但是version写入没有成功 { versionConfigChange = true; } VersionConfig toWriteVersionConfig = versionConfigChange ? serverVersionConfig : null; CheckResourceComplete(toWriteVersionConfig, checkResult, fileListBytes, versionVo); } else { if (GameStateManager.Instance.showGameStateLog) { UDebug.Log("本资源比较超前,不做资源版本更新: " + "persistentVersion" + persistentVersion.ToString() + " serverVersion:" + serverVersion.ToString()); } CheckResourceComplete(null, null, null, versionVo); } yield return(new WaitForEndOfFrame()); }
public static Byte[] stbi_loadfromfile(String filename, out int x, out int y, out int comp, int req_comp = 0) { Byte[] data = null; var ptr = IntPtr.Zero; x = 0; y = 0; comp = 0; try { ptr = stbi_load(filename, out x, out y, out comp, req_comp); if (ptr != IntPtr.Zero) { var size = x * y * comp; if (size > 0) { data = new byte[size]; Marshal.Copy(ptr, data, 0, size); } } } catch (Exception e) { if (!(e is DllNotFoundException)) { UDebug.LogException(e); } } finally { if (ptr != IntPtr.Zero) { stbi_image_free(ptr); } else { var errorPtr = stbi_failure_reason(); for ( ; ;) { if (errorPtr != IntPtr.Zero) { var error = Marshal.PtrToStringAnsi(errorPtr); if (!String.IsNullOrEmpty(error)) { UDebug.LogError("stbi_loadfromfile failed: {0}", error); break; } } UDebug.LogError("stbi_loadfromfile failed: reason unknown."); break; } } } return(data); }
/// <summary> /// /// </summary> /// <param name="serverVersionConfig">如果不为空,则需要写入</param> /// <param name="checkResult">如果不为空,则需要删除文件或者下载文件</param> /// <param name="fileListBytes">下载之后的文本列表</param> /// <param name="url"></param> /// <param name="random"></param> /// <returns></returns> IEnumerator StartDownRes(VersionConfig serverVersionConfig, byte[] fileListBytes, List <FileUpdateVo> fileVoList, FileUpdateVo versionVo) { FileUpdateVo fileUpdateVo; string url = versionVo.Url; string random = versionVo.Random; float allSize = Util.SumSize(fileVoList, fileVoList.Count); for (int i = 0; i < fileVoList.Count; i++) { GameStateManager.Instance.DownProgressHandle(GameStates.DownResource, fileVoList, i, allSize); fileUpdateVo = fileVoList[i]; WWW www = new WWW(fileUpdateVo.FileUrl); yield return(www); if (string.IsNullOrEmpty(www.error)) { Util.WriteFile(fileUpdateVo.PersistentPath, www.bytes); } else { UDebug.LogError(string.Format("{0}down failed:{1}", fileUpdateVo.FileUrl, www.error)); yield break; } www.Dispose(); } if (fileListBytes != null) { fileUpdateVo = new FileUpdateVo(AppConst.FileListName, url, random, string.Empty, 0); Util.WriteFile(fileUpdateVo.PersistentPath, fileListBytes); } if (serverVersionConfig != null) { if (File.Exists(versionVo.PersistentPath)) { File.Delete(versionVo.PersistentPath); string json = JsonUtility.ToJson(serverVersionConfig); File.WriteAllText(versionVo.PersistentPath, json); } } GameStateManager.Instance.DownProgressHandle(GameStates.DownResource, fileVoList, fileVoList.Count, allSize); yield return(new WaitForEndOfFrame()); DownResourceComplete(); }
/// <summary> /// 把当前场景的lightmap像素以HDR格式读取出来保存成未压缩的浮点格式 /// </summary> /// <returns></returns> unsafe static List <LightmapInfo> LoadAllLightmapData() { var litmapData = new List <LightmapInfo>(); var lightmaps = LightmapSettings.lightmaps; var count = 0; for (int j = 0; j < lightmaps.Length; ++j) { var out_data = IntPtr.Zero; var err = IntPtr.Zero; var width = 0; var height = 0; var assetPath = AssetDatabase.GetAssetPath(lightmaps[j].lightmapColor); var ld = new LightmapInfo(); ld.assetPath = assetPath; try { if (NativeAPI.LoadEXR(ref out_data, out width, out height, ld.assetPath, ref err) >= 0) { ld.pixels = new Vector4[width * height]; ld.width = width; ld.height = height; var src = ( Vector4 * )out_data; for (int n = 0; n < ld.pixels.Length; ++n) { ld.pixels[n] = *src++; } ++count; } else { if (err != IntPtr.Zero) { var errorInfo = Marshal.PtrToStringAnsi(err); UDebug.LogError(errorInfo); } } } finally { if (out_data != IntPtr.Zero) { NativeAPI.crt_free(out_data); } } litmapData.Add(ld); } return(count == lightmaps.Length ? litmapData : null); }
public void Realloc(int maxSize) { maxSize = MathLib.CeilPowerOfTwo(maxSize); if (maxSize != m_atlasSize) { if (m_pool != null) { m_poolHandle.Free(); } m_usedWidth = 0; m_usedHeight = 0; m_usedArea = 0; m_atlasSize = maxSize; m_pool = new NativeAPI.stbrp_node[m_atlasSize * 4]; UDebug.Assert(m_pool != null && m_pool.Length > 0); m_poolHandle = GCHandle.Alloc(m_pool, GCHandleType.Pinned); var packedRects = m_packedRects; m_packedRects = new List <NativeAPI.stbrp_rect>(); m_ctx = new NativeAPI.stbrp_context(); fixed(NativeAPI.stbrp_context *_ctx = &m_ctx) { NativeAPI.stbrp_init_target(_ctx, m_atlasSize, m_atlasSize, (NativeAPI.stbrp_node *)m_poolHandle.AddrOfPinnedObject(), m_pool.Length); NativeAPI.stbrp_setup_allow_out_of_mem(_ctx, 1); } for (int i = 0; i < packedRects.Count; ++i) { var rect = packedRects[i]; var _rect = new NativeAPI.stbrp_rect(); _rect.w = rect.w; _rect.h = rect.h; _rect.id = rect.id; if (!Add(rect)) { UDebug.LogError("Realloc failed!"); break; } } } }
public AssetBundle SyncLoadStreamingAssetsAB(string path) { StringBuilder sb = new StringBuilder(); #if UNITY_ANDROID && !UNITY_EDITOR sb.Append(Application.dataPath); sb.Append("!assets/"); #else sb.Append(Application.streamingAssetsPath); sb.Append(System.IO.Path.DirectorySeparatorChar); #endif sb.Append(path); try { AssetBundle ab = AssetBundle.LoadFromFile(sb.ToString()); return(ab); } catch (System.Exception e) { UDebug.LogError(e.Message); return(null); } }
private bool OnSaveCheck() { nameDic = new Dictionary <string, int>(); string[] contents = File.ReadAllLines(Application.dataPath + "/Character.csv"); for (int i = 0; i < contents.Length; i++) { if (string.IsNullOrEmpty(contents[i])) { continue; } string kv = contents[i]; string[] kvArray = kv.Split(','); nameDic.Add(kvArray[1], int.Parse(kvArray[0])); } for (int i = 0; i < nodeRootList.Count; i++) { StoryNode sn = nodeRootList[i] as StoryNode; if (string.IsNullOrEmpty(sn.characterName)) { sn.roleId = 0; continue; } else if (!nameDic.ContainsKey(sn.characterName)) { UDebug.LogError(sn.characterName + " is not exist!"); nameDic.Clear(); return(false); } else { sn.roleId = nameDic[sn.characterName]; } } nameDic.Clear(); return(true); }
private void Save() { SaveFileDlg pth = new SaveFileDlg(); pth.structSize = Marshal.SizeOf(pth); pth.filter = "bytes (*.bytes)"; pth.file = new string(new char[256]); pth.maxFile = pth.file.Length; pth.fileTitle = new string(new char[64]); pth.maxFileTitle = pth.fileTitle.Length; pth.initialDir = Application.dataPath + "/HotUpdateRes/Story"; // default path UDebug.Log(Application.dataPath + "/HotUpdateRes/Story"); pth.title = "保存story数据"; pth.defExt = "bytes"; pth.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008; Dictionary <string, int> plottext = new Dictionary <string, int>(); string path = Application.dataPath + "/HotUpdateRes/Config/PlotTextConfig.txt"; if (!File.Exists(path)) { UDebug.LogError("can not find file : " + path); return; } string[] text = File.ReadAllLines(path); bool isChangeConfig = false; for (int i = 2; i < text.Length; i++) { if (string.IsNullOrEmpty(text[i])) { continue; } string[] plot = text[i].Split('\t'); try { plottext.Add(plot[1], int.Parse(plot[0])); } catch (Exception e) { UDebug.Log(e.Message); UDebug.LogError("第一段:" + plot[0]); UDebug.LogError("第二段:" + plot[1]); throw; } } for (int i = 0; i < nodeRootList.Count; i++) { if (string.IsNullOrEmpty(((StoryNode)nodeRootList[i]).text)) { ((StoryNode)nodeRootList[i]).textId = 0; } else if (plottext.ContainsKey(((StoryNode)nodeRootList[i]).text)) { ((StoryNode)nodeRootList[i]).textId = plottext[((StoryNode)nodeRootList[i]).text]; } else { int pltid = plottext[plottext.Keys.Last <string>()] + 1; plottext.Add(((StoryNode)nodeRootList[i]).text, pltid); ((StoryNode)nodeRootList[i]).textId = pltid; isChangeConfig = true; } } if (isChangeConfig) { string[] newtext = new string[plottext.Count + 2]; int i = 2; newtext[0] = "id" + "\t" + "text"; newtext[1] = "int" + "\t" + "string"; foreach (var item in plottext) { newtext[i] = item.Value + "\t" + item.Key; i++; } File.WriteAllLines(Application.dataPath + "/HotUpdateRes/Config/PlotTextConfig.txt", newtext); } if (SaveFileDialog.GetSaveFileName(pth)) { string filepath = pth.file; //选择的文件路径; if (!OnSaveCheck()) { return; } bool isSuccess = BinaryUtil.ObjectToFile(filepath, nodeRootList[0]); if (isSuccess) { path = filepath; UDebug.Log("Save succeed!"); } else { UDebug.LogError("Save failed!"); } } }
private void DownErrorHandle(string path, string errorInfo) { UDebug.LogError(string.Format("{0}下载错误{1}", path, errorInfo)); popUpBox.Open("资源下载错误!", GameStateManager.Instance.Quit); }
unsafe static void _RepackLightmap() { var gos = Selection.gameObjects; var checkMSG = false; REOPEN: if (gos.Length == 0) { UDebug.LogError("Please select a GameObject in hierarchy to process!"); return; } var hierarchy = UnityUtils.GetHierarchyPath(gos[0].transform); if (!checkMSG) { checkMSG = true; if (!EditorUtility.DisplayDialog(Title, "请确认:处理的是原始场景,如果已经处理过,请重新加载场景。", "直接整", "好吧,重新加载场景")) { UnityEditor.SceneManagement.EditorSceneManager.OpenScene(currentScene); gos = new GameObject[] { GameObject.Find(hierarchy) }; goto REOPEN; } } // 经过测试,这个值确实是输出到了最终lightmap纹理中纹理单位的间隔 var Padding = LightmapEditorSettings.padding; Bounds bounds; var workingPath = CleanTempFolder(); var allRenderers = CollectAllLightmapedRenderers(gos, out bounds).Values.ToList(); // 把搜集到的原始Mesh重新保存成asset格式,便于后面的修改(FBX无法修改) var meshes = new Dictionary <Mesh, Mesh>(); for (int i = 0; i < allRenderers.Count; ++i) { var ri = allRenderers[i]; var srcMesh = ri.mesh; if (!srcMesh.isReadable) { UDebug.LogError("Mesh \"{0}\" is not readable!"); continue; } var mf = ri.renderer.transform.GetComponent <MeshFilter>(); if (mf == null) { continue; } Mesh dstMesh = null; if (!meshes.TryGetValue(srcMesh, out dstMesh)) { var assetPath = String.Format("{0}/{1}_{2}.mesh.asset", workingPath, srcMesh.name, meshes.Count); if (File.Exists(assetPath)) { AssetDatabase.DeleteAsset(assetPath); } AssetDatabase.CreateAsset(UnityEngine.Object.Instantiate <Mesh>(srcMesh), assetPath); dstMesh = AssetDatabase.LoadAssetAtPath <Mesh>(assetPath); meshes.Add(srcMesh, dstMesh); } //覆盖原始模型 mf.sharedMesh = dstMesh; } if (meshes.Count > 0) { var litmapData = LoadAllLightmapData(); if (litmapData == null) { UDebug.LogError("Load source lightmaps failed."); return; } var inputRects = new List <NativeAPI.stbrp_rect>(); var all_atlas_pixels = new Dictionary <int, AtlasPixelsPage>(); var lightmapRectInfoList = new List <LightmapRect>(); using (var tp = new TexturePacker()) { for (int i = 0; i < allRenderers.Count; ++i) { var ri = allRenderers[i]; var r = ri.renderer; var uv2BoundsInfo = GetMeshUV2Bounds(r); int lightmapIndex = uv2BoundsInfo.lightmapIndex; if (lightmapIndex >= 0 && lightmapIndex < litmapData.Count) { var lightmapData = litmapData[r.lightmapIndex]; var meshUVBounds = uv2BoundsInfo.srcUVBounds; var lightmapUVBounds = uv2BoundsInfo.lightmapUVBounds; Real fMinX = lightmapUVBounds.x * lightmapData.width; Real fMaxX = lightmapUVBounds.z * lightmapData.width; Real fMinY = lightmapUVBounds.y * lightmapData.height; Real fMaxY = lightmapUVBounds.w * lightmapData.height; #if LIGHTMAPREPACKER_PRECISION_HIGH int pixMinX = ( int )Math.Max(Math.Floor(lightmapUVBounds.x * lightmapData.width), 0); int pixMaxX = ( int )Math.Min(Math.Ceiling(lightmapUVBounds.z * lightmapData.width), lightmapData.width); int pixMinY = ( int )Math.Max(Math.Floor(lightmapUVBounds.y * lightmapData.height), 0); int pixMaxY = ( int )Math.Min(Math.Ceiling(lightmapUVBounds.w * lightmapData.height), lightmapData.height); #else int pixMinX = ( int )Math.Max(Mathf.Floor(lightmapUVBounds.x * lightmapData.width), 0); int pixMaxX = ( int )Math.Min(Mathf.Ceil(lightmapUVBounds.z * lightmapData.width), lightmapData.width); int pixMinY = ( int )Math.Max(Mathf.Floor(lightmapUVBounds.y * lightmapData.height), 0); int pixMaxY = ( int )Math.Min(Mathf.Ceil(lightmapUVBounds.w * lightmapData.height), lightmapData.height); #endif if (pixMaxX <= pixMinX || pixMaxY <= pixMinY) { UDebug.LogError("Invalid LightmapUV: {0}", UnityUtils.GetHierarchyPath(r.transform)); continue; } // 传入自己的TexturePacker之前,把border大小加上去 var rt = default(NativeAPI.stbrp_rect); rt.w = ( ushort )((pixMaxX - pixMinX) + Padding); rt.h = ( ushort )((pixMaxY - pixMinY) + Padding); var lightmapRect = new LightmapRect(); lightmapRect.renderer = r; lightmapRect.lightmapUVBounds = lightmapUVBounds; lightmapRect.meshUVBounds = meshUVBounds; lightmapRect.lightmapPixelBounds = new Vector4i(pixMinX, pixMinY, pixMaxX, pixMaxY); lightmapRect.lightmapPixelFBounds = new Vector4d(fMinX, fMinY, fMaxX, fMaxY); rt.id = lightmapRectInfoList.Count; inputRects.Add(rt); lightmapRectInfoList.Add(lightmapRect); } } tp.PackRects(inputRects.ToArray()); tp.ForEach( (page, atlasSize, rt) => { var lightmapRect = lightmapRectInfoList[rt.id]; var renderer = lightmapRect.renderer; var lightmapData = litmapData[renderer.lightmapIndex]; AtlasPixelsPage atlas_pixels; if (!all_atlas_pixels.TryGetValue(page, out atlas_pixels)) { atlas_pixels = new AtlasPixelsPage { pixels = new Vector4[atlasSize * atlasSize], size = atlasSize }; all_atlas_pixels.Add(page, atlas_pixels); } // 原始像素包围盒,不包含Border var i_minx = ( int )lightmapRect.lightmapPixelBounds.x; var i_miny = ( int )lightmapRect.lightmapPixelBounds.y; var i_maxx = ( int )lightmapRect.lightmapPixelBounds.z; var i_maxy = ( int )lightmapRect.lightmapPixelBounds.w; #if FIXING_LIGHTMAP_UVBORDER int rtOffset = Padding / 2; if (Padding > 0) { // 扩大边框,多拷贝一些边缘像素消除黑边 i_minx -= Padding / 2; i_miny -= Padding / 2; i_maxx += Padding - Padding / 2; i_maxy += Padding - Padding / 2; } #else int rtOffset = 0; #endif // lightmap像素块copy fixed(Vector4 * _atlas_pixels = atlas_pixels.pixels) { for (int y = i_miny; y < i_maxy; y++) { int dy = y - i_miny + (rt.y - rtOffset); if (dy < 0 || dy >= atlasSize) { continue; } // 纹理坐标需要翻转一下,像素是翻转了的 int _dy = atlasSize - 1 - dy; int _sy = lightmapData.height - 1 - y; int _dy_stride = _dy * atlasSize; int _sy_stride = _sy * lightmapData.width; for (int x = i_minx; x < i_maxx; x++) { int dx = x - i_minx + (rt.x - rtOffset); if (dx < 0 || dx >= atlasSize) { continue; } _atlas_pixels[_dy_stride + dx] = lightmapData.GetPixelClamped(x, _sy); } } } var uvBounds = new Vector4d(); Real errorX = 0; Real errorY = 0; Real errorZ = 0; Real errorW = 0; #if FIXING_LIGHTMAP_UVERROR errorX = lightmapRect.lightmapPixelFBounds.x - lightmapRect.lightmapPixelBounds.x; errorY = lightmapRect.lightmapPixelFBounds.y - lightmapRect.lightmapPixelBounds.y; errorZ = lightmapRect.lightmapPixelFBounds.z - lightmapRect.lightmapPixelBounds.z; errorW = lightmapRect.lightmapPixelFBounds.w - lightmapRect.lightmapPixelBounds.w; #endif uvBounds.x = ((rt.x + errorX) / ( Real )atlasSize); uvBounds.y = ((rt.y + errorY) / ( Real )atlasSize); // 计算在新的lightmap纹理下的纹理坐标包围盒,由于pack之前我们人为加了一个Padding,所以这里计算要减去 uvBounds.z = (((rt.x + rt.w + errorZ) - Padding) / ( Real )atlasSize); uvBounds.w = (((rt.y + rt.h + errorW) - Padding) / ( Real )atlasSize); if (Mathf.Approximately(( float )lightmapRect.meshUVBounds.z, ( float )lightmapRect.meshUVBounds.x) || Mathf.Approximately(( float )lightmapRect.meshUVBounds.w, ( float )lightmapRect.meshUVBounds.y)) { // 无效 renderer.lightmapIndex = -1; renderer.lightmapScaleOffset = new Vector4(1, 1, 0, 0); UDebug.LogError("Invalid LightmapUV's bounds: {0}", UnityUtils.GetHierarchyPath(lightmapRect.renderer.transform)); } else { // 计算新的ScaleOffset,映射到新的lightmap纹理 renderer.lightmapIndex = page; var sf = CalculateUVScaleOffset(lightmapRect.meshUVBounds, uvBounds); renderer.lightmapScaleOffset = new Vector4(( float )sf.x, ( float )sf.y, ( float )sf.z, ( float )sf.w); } } ); if (all_atlas_pixels.Count > 0) { var lightmapOutputPath = workingPath; var lightmaps = new LightmapData[all_atlas_pixels.Count]; var lightmapPathList = new List <KeyValuePair <String, int> >(all_atlas_pixels.Count); int pageIndex = 0; foreach (var pagePixels in all_atlas_pixels) { fixed(Vector4 *_atlas_pixels = pagePixels.Value.pixels) { EditorUtility.DisplayProgressBar(Title, "Saving lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count); pageIndex++; int atlasSize = pagePixels.Value.size; var path = String.Format("{0}/lightmap_{1}.exr", lightmapOutputPath, pagePixels.Key); if (File.Exists(path)) { AssetDatabase.DeleteAsset(path); } NativeAPI.SaveEXR(( IntPtr )_atlas_pixels, atlasSize, atlasSize, 4, 0, path); lightmapPathList.Add(new KeyValuePair <String, int>(path, pagePixels.Key)); } } try { AssetDatabase.Refresh(); pageIndex = 0; for (int j = 0; j < lightmapPathList.Count; j++) { var path = lightmapPathList[j].Key; var page = lightmapPathList[j].Value; EditorUtility.DisplayProgressBar(Title, "Apply lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count); pageIndex++; var ti = AssetImporter.GetAtPath(path) as TextureImporter; if (ti != null) { if (ti.textureType != TextureImporterType.Lightmap || ti.isReadable || ti.wrapMode != TextureWrapMode.Clamp) { ti.textureType = TextureImporterType.Lightmap; ti.isReadable = false; ti.wrapMode = TextureWrapMode.Clamp; AssetDatabase.ImportAsset(ti.assetPath); } var tex = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; if (tex != null) { lightmaps[page] = new LightmapData(); lightmaps[page].lightmapColor = tex; } } } } finally { LightmapSettings.lightmaps = lightmaps; } } } } }
unsafe static void _RepackLightmap() { var gos = Selection.gameObjects; var checkMSG = false; REOPEN: if (gos.Length == 0) { UDebug.LogError("Please select a GameObject in hierarchy to process!"); return; } var hierarchy = UnityUtils.GetHierarchyPath(gos[0].transform); if (!checkMSG) { checkMSG = true; if (!EditorUtility.DisplayDialog(Title, "请确认:处理的是原始场景,如果已经处理过,请重新加载场景。", "直接整", "好吧,重新加载场景")) { UnityEditor.SceneManagement.EditorSceneManager.OpenScene(currentScene); gos = new GameObject[] { GameObject.Find(hierarchy) }; goto REOPEN; } } // 经过测试,这个值确实是输出到了最终lightmap纹理中纹理单位的间隔 var Padding = LightmapEditorSettings.padding; Bounds bounds; var workingPath = CleanTempFolder(); var allRenderers = CollectAllLightmapedRenderers(gos, out bounds).Values.ToList(); // 把搜集到的原始Mesh重新保存成asset格式,便于后面的修改(FBX无法修改) var meshes = new Dictionary <Mesh, Mesh>(); for (int i = 0; i < allRenderers.Count; ++i) { var ri = allRenderers[i]; var srcMesh = ri.mesh; if (!srcMesh.isReadable) { UDebug.LogError("Mesh \"{0}\" is not readable!"); continue; } var mf = ri.renderer.transform.GetComponent <MeshFilter>(); if (mf == null) { continue; } Mesh dstMesh = null; if (!meshes.TryGetValue(srcMesh, out dstMesh)) { var assetPath = String.Format("{0}/{1}_{2}.mesh.asset", workingPath, srcMesh.name, meshes.Count); if (File.Exists(assetPath)) { AssetDatabase.DeleteAsset(assetPath); } AssetDatabase.CreateAsset(UnityEngine.Object.Instantiate <Mesh>(srcMesh), assetPath); dstMesh = AssetDatabase.LoadAssetAtPath <Mesh>(assetPath); meshes.Add(srcMesh, dstMesh); } //覆盖原始模型 mf.sharedMesh = dstMesh; } if (meshes.Count > 0) { var litmapData = LoadAllLightmapData(); if (litmapData == null) { UDebug.LogError("Load source lightmaps failed."); return; } var inputRects = new List <NativeAPI.stbrp_rect>(); var all_atlas_pixels = new Dictionary <int, AtlasPixelsPage>(); var lightmapRectInfoList = new List <LightmapRect>(); using (var tp = new TexturePacker()) { for (int i = 0; i < allRenderers.Count; ++i) { var ri = allRenderers[i]; var r = ri.renderer; var uv2BoundsInfo = GetMeshUV2Bounds(r); int lightmapIndex = uv2BoundsInfo.lightmapIndex; if (lightmapIndex >= 0 && lightmapIndex < litmapData.Count) { var lightmapData = litmapData[r.lightmapIndex]; var meshUVBounds = uv2BoundsInfo.srcUVBounds; var lightmapUVBounds = uv2BoundsInfo.lightmapUVBounds; var _lightmapUVBounds = lightmapUVBounds; // 当前发现有些美术自己展开的UV有超过01现象,尝试自己模拟一下Repeat采样纹理坐标的计算 _lightmapUVBounds.x = MathLib.ClampRepeatUV(_lightmapUVBounds.x); _lightmapUVBounds.y = MathLib.ClampRepeatUV(_lightmapUVBounds.y); _lightmapUVBounds.z = MathLib.ClampRepeatUV(_lightmapUVBounds.z); _lightmapUVBounds.w = MathLib.ClampRepeatUV(_lightmapUVBounds.w); // 防止包围盒上下左右颠倒,重新翻转一下 if (_lightmapUVBounds.x > _lightmapUVBounds.z) { var temp = _lightmapUVBounds.x; _lightmapUVBounds.x = _lightmapUVBounds.z; _lightmapUVBounds.z = temp; } if (_lightmapUVBounds.y > _lightmapUVBounds.w) { var temp = _lightmapUVBounds.y; _lightmapUVBounds.y = _lightmapUVBounds.w; _lightmapUVBounds.w = temp; } // 纹理坐标到像素坐标转换,此处代码查看了网上流传出来unity4.3里面源码 var i_minx = Mathf.FloorToInt(_lightmapUVBounds.x * ( float )lightmapData.width); var i_miny = Mathf.FloorToInt(_lightmapUVBounds.y * ( float )lightmapData.height); var i_width = Mathf.CeilToInt((_lightmapUVBounds.z - _lightmapUVBounds.x) * ( float )lightmapData.width); var i_height = Mathf.CeilToInt((_lightmapUVBounds.w - _lightmapUVBounds.y) * ( float )lightmapData.height); if (i_width <= 0 || i_height <= 0) { UDebug.LogError("Invalid LightmapUV: {0}", UnityUtils.GetHierarchyPath(r.transform)); continue; } var i_maxx = i_minx + i_width; var i_maxy = i_miny + i_height; i_minx = Mathf.Clamp(i_minx, 0, lightmapData.width); i_maxx = Mathf.Clamp(i_maxx, 0, lightmapData.width); i_miny = Mathf.Clamp(i_miny, 0, lightmapData.height); i_maxy = Mathf.Clamp(i_maxy, 0, lightmapData.height); // 传入自己的TexturePacker之前,把border大小加上去 var rt = default(NativeAPI.stbrp_rect); rt.w = ( ushort )(i_width + Padding); rt.h = ( ushort )(i_height + Padding); var lightmapRect = new LightmapRect(); lightmapRect.renderer = r; lightmapRect.lightmapUVBounds = lightmapUVBounds; lightmapRect.meshUVBounds = meshUVBounds; lightmapRect.lightmapPixelBounds = new Vector4(i_minx, i_miny, i_maxx, i_maxy); rt.id = lightmapRectInfoList.Count; inputRects.Add(rt); lightmapRectInfoList.Add(lightmapRect); } } tp.PackRects(inputRects.ToArray()); tp.ForEach( (page, atlasSize, rt) => { var lightmapRect = lightmapRectInfoList[rt.id]; var renderer = lightmapRect.renderer; var lightmapData = litmapData[renderer.lightmapIndex]; AtlasPixelsPage atlas_pixels; if (!all_atlas_pixels.TryGetValue(page, out atlas_pixels)) { atlas_pixels = new AtlasPixelsPage { pixels = new Vector4[atlasSize * atlasSize], size = atlasSize }; all_atlas_pixels.Add(page, atlas_pixels); } int i_minx = ( int )lightmapRect.lightmapPixelBounds.x; int i_miny = ( int )lightmapRect.lightmapPixelBounds.y; int i_maxx = ( int )lightmapRect.lightmapPixelBounds.z; int i_maxy = ( int )lightmapRect.lightmapPixelBounds.w; // lightmap像素块copy fixed(Vector4 * _atlas_pixels = atlas_pixels.pixels) { for (int y = i_miny; y < i_maxy; y++) { int dy = y - i_miny + rt.y; // 纹理坐标需要翻转一下,像素是翻转了的 int _dy = atlasSize - 1 - dy; int _sy = lightmapData.height - 1 - y; int _dy_stride = _dy * atlasSize; int _sy_stride = _sy * lightmapData.width; for (int x = i_minx; x < i_maxx; x++) { int dx = x - i_minx + rt.x; _atlas_pixels[_dy_stride + dx] = lightmapData.pixels[_sy_stride + x]; } } } // 计算在新的lightmap纹理下的纹理坐标包围盒,由于pack之前我们认为加了一个Padding,所以这里计算要减去 // 这里估计会有各种影藏的因素导致最终效果和原始效果出现偏差,黑边,偏移,防缩等 // 因为在复制像素的时候,包围盒因取整引入了误差,这里为了防止出现黑边,我人为的往里缩小了0.5 Vector4 uvBounds; uvBounds.x = ( float )(rt.x + 0.5f) / ( float )atlasSize; uvBounds.y = ( float )(rt.y + 0.5f) / ( float )atlasSize; uvBounds.z = ( float )((rt.x + rt.w) - Padding - 0.5f) / ( float )atlasSize; uvBounds.w = ( float )((rt.y + rt.h) - Padding - 0.5f) / ( float )atlasSize; if (Mathf.Approximately(lightmapRect.meshUVBounds.z, lightmapRect.meshUVBounds.x) || Mathf.Approximately(lightmapRect.meshUVBounds.w, lightmapRect.meshUVBounds.y)) { // 无效 renderer.lightmapIndex = -1; renderer.lightmapScaleOffset = new Vector4(1, 1, 0, 0); UDebug.LogError("Invalid LightmapUV's bounds: {0}", UnityUtils.GetHierarchyPath(lightmapRect.renderer.transform)); } else { // 计算新的ScaleOffset,映射到新的lightmap纹理 renderer.lightmapIndex = page; renderer.lightmapScaleOffset = MathLib.CalculateUVScaleOffset(lightmapRect.meshUVBounds, uvBounds); } } ); if (all_atlas_pixels.Count > 0) { var lightmapOutputPath = workingPath; var lightmaps = new LightmapData[all_atlas_pixels.Count]; var lightmapPathList = new List <KeyValuePair <String, int> >(all_atlas_pixels.Count); int pageIndex = 0; foreach (var pagePixels in all_atlas_pixels) { fixed(Vector4 *_atlas_pixels = pagePixels.Value.pixels) { EditorUtility.DisplayProgressBar(Title, "Saving lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count); pageIndex++; int atlasSize = pagePixels.Value.size; var path = String.Format("{0}/lightmap_{1}.exr", lightmapOutputPath, pagePixels.Key); if (File.Exists(path)) { AssetDatabase.DeleteAsset(path); } NativeAPI.SaveEXR(( IntPtr )_atlas_pixels, atlasSize, atlasSize, 4, 0, path); lightmapPathList.Add(new KeyValuePair <String, int>(path, pagePixels.Key)); } } try { AssetDatabase.Refresh(); pageIndex = 0; for (int j = 0; j < lightmapPathList.Count; j++) { var path = lightmapPathList[j].Key; var page = lightmapPathList[j].Value; EditorUtility.DisplayProgressBar(Title, "Apply lightmap atlas...", ( float )pageIndex / ( float )all_atlas_pixels.Count); pageIndex++; var ti = AssetImporter.GetAtPath(path) as TextureImporter; if (ti != null) { if (ti.textureType != TextureImporterType.Lightmap || ti.isReadable || ti.wrapMode != TextureWrapMode.Clamp) { ti.textureType = TextureImporterType.Lightmap; ti.isReadable = false; ti.wrapMode = TextureWrapMode.Clamp; AssetDatabase.ImportAsset(ti.assetPath); } var tex = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; if (tex != null) { lightmaps[page] = new LightmapData(); lightmaps[page].lightmapLight = tex; } } } } finally { LightmapSettings.lightmaps = lightmaps; } } } } }
void CreateAnimationButtons() { skillIDDict.Clear(); animationButtons.Clear(); animationButtonSource.gameObject.SetActive(true); while (animationButtonSource.transform.parent.childCount > 1) { if (animationButtonSource.transform.parent.GetChild(0).name == animationButtonSource.gameObject.name) { DestroyImmediate(animationButtonSource.transform.parent.GetChild(1).gameObject); } else { DestroyImmediate(animationButtonSource.transform.parent.GetChild(0).gameObject); } } if (m_mainRole != null) { if (m_mainRole.GetComponent <Animation>() != null) { m_roleAnim = m_mainRole.GetComponent <Animation>(); if (m_PrefabSkillID != null) { bool isFounding = true; while (isFounding) { isFounding = false; foreach (AnimationState state in m_roleAnim) { isFounding = true; m_roleAnim.RemoveClip(state.clip); } } checkNone = false; for (int i = 0; i < m_PrefabSkillID.m_Animations.Count; i++) { if (m_PrefabSkillID.m_Animations[i] != null) { m_roleAnim.AddClip(m_PrefabSkillID.m_Animations[i], m_PrefabSkillID.m_Animations[i].name + "/" + m_PrefabSkillID.m_SkillIDList[i].ToString()); } else { Debug.LogException(new NoneObjectException(string.Format("{0}的第{1}个AnimationClip为空!!!", m_mainRole.name, i)), m_RSS); checkNone = true; } } if (checkNone) { EditorApplication.ExecuteMenuItem("Edit/Play"); } if (m_roleAnim.GetClip("idle/0") != null) { m_roleAnim.clip = m_roleAnim.GetClip("idle/0"); } else { m_roleAnim.clip = m_roleAnim.GetClip(m_PrefabSkillID.m_Animations[0].name); } currentState = m_roleAnim[m_roleAnim.clip.name]; m_roleAnim.Play(currentState.name); } int index = -1; foreach (AnimationState state in m_roleAnim) { index += 1; int tempIndex = index; Button button = Instantiate(animationButtonSource, animationButtonSource.transform.parent); button.name = " " + state.clip.name; button.transform.Find("Name").GetComponent <Text>().text = button.name.Substring(0, button.name.IndexOf('/')); button.transform.Find("Time").GetComponent <Text>().text = string.Format("{0:0.00}", state.length); button.onClick.AddListener(delegate { if (playTogetherToggle.isOn) { Button newBtn = Instantiate(button, playTogetherTransform); newBtn.name = button.name; newBtn.onClick.RemoveAllListeners(); newBtn.onClick.AddListener(delegate { DestroyImmediate(newBtn.gameObject); }); } else { m_roleAnim.Play(state.name, PlayMode.StopAll); lastState = currentState; currentState = m_roleAnim[state.name]; PlaySFX(button.name, m_PrefabSkillID.m_SkillIDList[tempIndex], m_SFXLevel); frameCount = ( int )(state.length * state.clip.frameRate); animSlider.maxValue = frameCount; } }); animationButtons.Add(state.name, button); skillIDDict.Add(state.clip.name, tempIndex); } animationButtonSource.gameObject.SetActive(false); } else { UDebug.LogError("There's no animation attatched to the player!!!!!"); } } else { UDebug.LogError("No player exist!!!!!!"); } }