Unity 5.x動態載入光照資訊(所有坑已踩)
阿新 • • 發佈:2019-02-15
能搜到這的應該是被新的烘焙系統坑了少時間,4.x到5.x美術必須重新烘焙,關於美術的沒什麼說的,只有---重新烘焙!
新的烘焙系統,為了相容5.x的多場景編輯功能,將烘焙資訊從mesh全部挪到了一箇中間件xxx.assets,這個資原始檔在5.x烘焙完成後和光照貼圖存放在一起,然而關於這個資原始檔,我是查來查去沒有找到任何介面可以訪問。
只能百度谷歌,發現方案基本都是序列化,因為上面提到的烘焙資訊沒有在mesh中儲存,而是一個雞肋資原始檔,釋出時xxx.assets可以刪了。
序列化哪些資料,在編輯器面板能看到,在下面程式碼中也能看到。
編輯器指令碼PrefabLightmapDataEditor.cs:
1 using UnityEngine; 2 using UnityEditor; 3 4 public class PrefabLightmapDataEditor : Editor { 5 [MenuItem("Ojcgames Tools/儲存該場景預製件的烘焙資訊", false, 0)] 6 static void SaveLightmapInfoByGameObject() 7 { 8 GameObject go = Selection.activeGameObject; 9 10 if(null== go)return; 11 12 PrefabLightmapData data = go.GetComponent<PrefabLightmapData>(); 13 if (data == null) 14 { 15 data = go.AddComponent<PrefabLightmapData>(); 16 } 17 //save lightmapdata info by mesh.render 18 data.SaveLightmap();19 20 EditorUtility.SetDirty(go); 21 //applay prefab 22 PrefabUtility.ReplacePrefab(go, PrefabUtility.GetPrefabParent(go), ReplacePrefabOptions.ConnectToPrefab); 23 } 24 }
被繫結在預製件父級上的序列化指令碼PrefabLightmapData.cs:
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 5 public class PrefabLightmapData : MonoBehaviour 6 { 7 [System.Serializable] 8 struct RendererInfo 9 { 10 public Renderer renderer; 11 public int lightmapIndex; 12 public Vector4 lightmapOffsetScale; 13 } 14 15 #if UNITY_EDITOR 16 [UnityEngine.SerializeField] 17 Texture2D[] lightmapTexs; //當前場景的燈光貼圖 18 #endif 19 20 [UnityEngine.SerializeField] 21 RendererInfo[] rendererList; 22 23 #if UNITY_EDITOR 24 public void SaveLightmap() 25 { 26 Renderer[] renders = GetComponentsInChildren<Renderer>(true); 27 RendererInfo rendererInfo; 28 rendererList = new RendererInfo[renders.Length]; 29 30 int index = 0; 31 32 for(int r = 0, rLength = renders.Length; r<rLength; ++r) 33 { 34 if (renders[r].gameObject.isStatic == false) continue; 35 36 rendererInfo.renderer = renders[r]; 37 rendererInfo.lightmapIndex = renders[r].lightmapIndex; 38 rendererInfo.lightmapOffsetScale = renders[r].lightmapScaleOffset; 39 40 rendererList[index] = rendererInfo; 41 42 ++index; 43 } 44 45 //序列化光照貼圖 46 LightmapData[] ldata = LightmapSettings.lightmaps; 47 lightmapTexs = new Texture2D[ldata.Length]; 48 for(int t = 0, tLength = ldata.Length; t<tLength; ++t) 49 { 50 lightmapTexs[t] = ldata[t].lightmapFar; 51 } 52 } 53 54 void Awake() 55 { 56 this.LoadLightmap(); 57 } 58 #endif 59 60 #if !UNITY_EDITOR 61 public 62 #endif 63 void LoadLightmap() 64 { 65 if(null == rendererList || rendererList.Length == 0) 66 { 67 Debug.Log(gameObject.name + " 的 光照資訊為空"); 68 return; 69 } 70 71 Renderer[] renders = GetComponentsInChildren<Renderer>(true); 72 73 for(int r = 0, rLength = renders.Length; r<rLength; ++r) 74 { 75 renders[r].lightmapIndex = rendererList[r].lightmapIndex; 76 renders[r].lightmapScaleOffset = rendererList[r].lightmapOffsetScale; 77 } 78 79 #if UNITY_EDITOR 80 if(null == lightmapTexs || lightmapTexs.Length == 0) 81 { 82 return; 83 } 84 85 LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional; 86 LightmapData[] ldata = new LightmapData[lightmapTexs.Length]; 87 LightmapSettings.lightmaps = null; 88 89 for(int t = 0, tLength = lightmapTexs.Length; t<tLength; ++t) 90 { 91 ldata[t] = new LightmapData(); 92 ldata[t].lightmapFar = lightmapTexs[t]; 93 } 94 95 LightmapSettings.lightmaps = ldata; 96 #endif 97 } 98 }
其中
Texture2D[] lightmapTexs;
Awake();
是我為了方便美術測試,釋出專案中,我手動管理何時載入光照資訊和光照貼圖,至此程式碼已提供完。
下面說點碰到的坑:
1、PC正常,釋出到android或ios完全看不到光照資訊,並且序列化引數都正確,光照貼圖也載入正常,LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional 設定正常:
在釋出時,Edit - Project Settings - Graphics - Shader Stripping - Lightmap modes - Manual
關於該選項的官方說明:By default, Unity looks at your scenes and lightmapping settings to figure out which Fog and Lightmapping modes are used; and skips corresponding shader variants. This saves game build data size, and improves loading times.
也就是說,如果你想用指令碼動態的控制,那麼就得將這裡設定為手動模式。
2、最後一個坑就是不能完全相信搜尋結果,他人記錄的可能只是針對其出現的問題。