- Home /
How the heck can I include Lightmapping data in unity 5 asset bundles???
I cannot find any way to export a prefab into an asset bundle and include the lightmap data. With unity4 I could read Lightmap assets and later at load time assign them back to LightmapSettings. Using the new Enlighten it is stubbornly hiding the Textures, for no reason, they can't be read and are no assets either.
WebGL is great, performance of my migrated project is great, all is great, except that unity 5 threw out Beast for no apparent reason, forcing me to rebake all scenes and not allowing me to edit lightmaps in Photoshop.
This way the whole of Unity5 is worthless.
I have tried both the old and the new AssetBundle systems and can't also manage to load the baked scene from AssetBundles together with lightmaps, no matter what kind of lightmaps I use (directional, non-directional, diffuse) and no matter what material shaders I use (standard, legacy) - in WebGL.
Did you find a work around? I'm having the same issue. Thanks
I have just icluded a "blind" lightmapped scene in the main build and that helped.
I.e. the loading scene had just a loader, no lightmaps, no geometry.
Then I made just a simple scene, which I do not use, but it contains a lightmapped plane and a box. Since including it into the build, the other scenes loaded from asset bundles do load with lightmaps. Seems strange, doesn't it?
Absolutely. Apparently the Lightmapping System gets stripped out otherwise (even if stripping is deactivated).
Thanks a lot, I will try that out.
Also there is a new unity version out which says in the release notes "•Asset Loading: Fixed loading of GI data from an AssetBundle" - maybe that already does the trick.
Answer by eyalfx · May 08, 2015 at 10:26 PM
I won't be able to try the new version since I'm heading out to vacation for a week and NOT taking my laptop :) But I did get it to work with the following scripts:
First I made a new class that save the index and coordinates of the lightmap.
public class LightmapParam : MonoBehaviour {
public int lightmapIndex;
public Vector4 lightmapScaleOffset;
}
I build the asset using this script, making sure to add a LIghtmapParam to each object that has a renderer. And manually adding the lightmaps to the assetBundle
private void BuildAssetBundle(){
GameObject assetParent = new GameObject();
assetParent.name = assetName;
GameObject[] allObjects = UnityEngine.Object.FindObjectsOfType<GameObject>() ;
foreach(GameObject obj in allObjects){
if(assetParent != obj){
obj.transform.SetParent(assetParent.transform, true);
Renderer r = obj.GetComponent<Renderer>();
if(r != null){
LightmapParam lmp = obj.GetComponent<LightmapParam>();
if(lmp == null)
lmp = obj.AddComponent<LightmapParam>();
lmp.lightmapIndex = r.lightmapIndex;
lmp.lightmapScaleOffset = r.lightmapScaleOffset;
}
}
}
string path = "Assets/AssetPrefabs/" + assetName + ".prefab";
PrefabUtility.CreatePrefab(path, assetParent, ReplacePrefabOptions.ReplaceNameBased);
Debug.Log("prefab " + path);
//AssetBundleBuild[] abb = new AssetBundleBuild[1];
//abb[0].assetBundleName = assetName;
//abb[0].assetNames = new string[]{ path};
//BuildPipeline.BuildAssetBundles ("Assets/AssetBundles", abb);
string curScene = EditorApplication.currentScene;
string[] parts = curScene.Split('/', '\\');
string sceneName = parts[parts.Length - 1].Split('.')[0];
string lightmapPath = Path.GetDirectoryName(curScene) + "/" + sceneName + "/";
List<string> assetList = new List<string>();
for(int i = 0; i < LightmapSettings.lightmaps.Length; i++){
LightmapData lmd = LightmapSettings.lightmaps[i];
string lmp = lightmapPath + "Lightmap-" + i + "_comp_light.exr";
assetList.Add(lmp );
Debug.Log(lmp + " " + File.Exists(lmp));
}
Debug.Log(assetList[0] + " " + assetList.Count);
//string path = "Assets/AssetPrefabs/" + assetName + ".prefab";
assetList.Add(path);
AssetBundleBuild[] abb = new AssetBundleBuild[1]; // *************************************** lightmaps 2
abb[0].assetNames = assetList.ToArray();// new string[]{ path}; // create asset bundle from this prefab
// build mac
Debug.Log("make osx bundle");
abb[0].assetBundleName = assetName + "_osx.unity3d";
BuildPipeline.BuildAssetBundles ("Assets/AssetBundles", abb, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
}
Then when I'm loading the assetBundle I'm looking for the lightmapParam and assigning the values. and assigning the actual maps to the lightmapSettings.
AssetBundle bundle = www.assetBundle;
Object[] objects = bundle.LoadAllAssets<Object>();
List<LightmapData> lmdList = new List<LightmapData>();
foreach(Object obj in objects){
if (obj.GetType () == typeof(Texture2D)) {
if (obj.name.Contains ("Lightmap")) {
LightmapData lmd = new LightmapData();
Texture2D tex = obj as Texture2D;
lmd.lightmapFar = tex;
lmdList.Add(lmd);
}
}
}
LightmapSettings.lightmaps = lmdList.ToArray();
currentScene = Instantiate(bundle.LoadAsset(currentAsset.objectId)) as GameObject;
Renderer[] rndrs = GameObject.FindObjectsOfType<Renderer>();
foreach(Renderer rnd in rndrs){
LightmapParam lmp = rnd.GetComponent<LightmapParam>();
if(lmp != null){
//Debug.Log(rnd.name + " " + lmp.lightmapIndex + " " + lmp.lightmapScaleOffset);
rnd.lightmapIndex = lmp.lightmapIndex;
rnd.lightmapScaleOffset = lmp.lightmapScaleOffset;
rnd.gameObject.isStatic = true;
}
}
Hope this works for you as well. The one gatcha that I found is that the lightmaps coming in from the bundle are not tagged Lightmaps, and I couldn't find a way to change that , so not all shaders work with it. I use legacy>lightmap>diffuse and it works Cheers
Wow, thank you a lot for the detailed answer. I will test this approach (tomorrow, late right now), looks like it's going to work even with Beast, since you are basically transferring the lightmap settings manually.
And yes, very wise idea to leave the laptop at home.
It works! I managed to get unity4 Beast lightmapping running in unity5 webGL. I followed your approach. I had an earlier similar approach where I exported the lightmap settings and reimported them in the unit5 scene, but I did not realize these things, which ultimately let me fail: 1. when exporting the bundle, unity resets the lightmap settings and they need to be restored at runtime 2. the correct LightmapSettings.lightmaps$$anonymous$$ode must be set, otherwise textures appear black/white or whatever 3. Imported lightmaps need to be refreshed (the intensity is wrong, simply changing something and then back and applying does the trick) 4. WebGL uses caching (both filesystem storage and browser cache), which made me load old bundles and wonder why the heck it wouldn't work online when it was working in the editor
Thanks a lot for giving me hope again so I retried. I might post a full article how to migrate a unity4 Beast-mapped project to unity5 without having to rebake it later.
oh btw, you don't need to collect the lightmaps manually. just extend your LightmapParams and also save a reference to the lightmap from lightmapsdata[index].lightmapNear etc. This will automatically include them in the assetbundle - using the correct import type!
Hi, I'm back. Glad it works. How do you set the lightmap settings to LightmapSettings.lightmaps$$anonymous$$ode . I haven't found a way to do it in runtime. Also what do you mean by refresh (changing something and changing back). Great tip about referencing the lightmap in LightmapParams. I'll do it too. Last question. What software are using to write the lightmaps? $$anonymous$$aya? Thanks for posting.
Hi. I put a new answer to the topic containing my code.
The lightmaps were made in a half-manual fashion - rendered in unity4 Beast and then edited in Photoshop by hand, boosted etc. One reason why Enlighten sucks (doesn't allow you to edit them any more to remove all the bugs in indoor scenes), and also the reason why I can't just rebake my scenes.
Answer by frevd · May 21, 2015 at 06:57 AM
This is the component I use to store the lightmap settings (they must be setup correctly in the editor, but need to be preserved in order to be exported to a bundle). See StoreAll static method (which I call from an editor action in a separate script). It references the lightmaps directly so you won't have trouble later setting the right import settings for the textures.
At runtime when I load the bundle I have this script in the main project as well (since scripts don't get exported due to Apple's policies of having code in the main executable). At runtime I call RestoreAll and pass the desired Lightmap mode. I only tested this for static single nondirectional lightmaps though (I migrated unity4 Beast with that).
In order to migrate Beast lightmaps, I made an utility to export the lightmap parameters to a textfile and load them again up in unity5, since unity5 would simply clear every setting from Beast (same as what happens at bundle export time). The lightmaps contain bugs and aren't perfect, but a little adjustment is better than rebaking, at least in my indoor scenes. Of course when you restore the lightmap data, the lightmaps must also be present in the scene.
Regarding the lightmaps I had an intensity issue when simply importing the EXR assets from Beast in unity5, but I found it can be solved rather easily by changing something on the textures and pressing the apply button (and then changing that something back, it's only about the re-encoding step done by unity5, since lightmapping in unity5 is not using the 2x factor any more).
So, I hope this helps anybody running into the same problems.
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// Use the provided editor action to put this component on all objects that use static light maps, in order to have their lightmap parameters exported to an asset bundle and later restored properly.
/// The corresponding lightmaps will automatically be referenced and included in the bundle. At loading time you need to have this script in your hosting project and call the static method RestoreAll.
/// </summary>
public class LightmapParams : MonoBehaviour
{
public Texture2D lightmapNear, lightmapFar;
public int lightmapIndex;
public Vector4 lightmapScaleOffset;
/// <summary>This function is called from an editor action and creates or updates this component on all objects with renderers and static lightmap in the current scene. </summary>
public static void StoreAll()
{
foreach (Renderer r in FindObjectsOfType<Renderer>())
if (r.lightmapIndex != -1)
{
LightmapParams lmp = r.gameObject.GetComponent<LightmapParams>();
if (!lmp)
lmp = r.gameObject.AddComponent<LightmapParams>();
lmp.lightmapIndex = r.lightmapIndex;
lmp.lightmapScaleOffset = r.lightmapScaleOffset;
lmp.lightmapNear = LightmapSettings.lightmaps[lmp.lightmapIndex].lightmapNear;
lmp.lightmapFar = LightmapSettings.lightmaps[lmp.lightmapIndex].lightmapFar;
}
}
/// <summary>This function needs to be called after importing an assetbundle with exported lightmap data (see <see cref="StoreAll"/>), in order to restore it to the object. The collection it lightmaps will be set from the set of all lightmaps of all <see cref="LightmapParams"/> instances.</summary>
public static void RestoreAll(LightmapsMode mode, bool removeComponentsAfterwards = false, bool setStatic = false)
{
List<LightmapData> newLightmaps = new List<LightmapData>();
foreach (LightmapParams p in FindObjectsOfType<LightmapParams>())
{
Renderer r = p.gameObject.GetComponent<Renderer>();
if (!r)
continue;
r.lightmapIndex = p.lightmapIndex;
r.lightmapScaleOffset = p.lightmapScaleOffset;
// collect lightmaps from references:
while (newLightmaps.Count <= p.lightmapIndex)
newLightmaps.Add(new LightmapData());
newLightmaps[p.lightmapIndex].lightmapNear = p.lightmapNear;
newLightmaps[p.lightmapIndex].lightmapFar = p.lightmapFar;
if (setStatic)
r.gameObject.isStatic = true;
if (removeComponentsAfterwards)
Destroy(p);
}
// activate:
LightmapSettings.lightmaps = newLightmaps.ToArray();
LightmapSettings.lightmapsMode = mode;
}
/// <summary>This function is called from an editor action to remove all <see cref="LightmapParams"/> components in the scene.</summary>
public static void RemoveAll()
{
foreach (LightmapParams p in FindObjectsOfType<LightmapParams>())
DestroyImmediate(p);
}
}
Best, Matt
Hi can you tell me how to hook up unity 4 lightmaps in unity 5 for mobile platform ? the above methods wrks for mobile platform wrks too ?
@frevd, Hi ,
Thanks for the awesome code, It really worked for me in IDE, but when I try to run the same code in the device , light map is not working. Any inputs on that?
Thanks.
Tanveer
@frevd, Hi ,
Thanks for the awesome code, It really worked for me in IDE, but when I try to run the same code in the device , light map is not working. Any inputs on that?
Thanks.
Tanveer.
Answer by pravinyadav · Jul 02, 2015 at 12:52 PM
Hi frevd, Thanks for all your explanation. I am trying to get 4.6.1 beast lightmapping in Unity 5.1.1 WebGL. I followed the process as mentioned below 1. Built Assetbundles in Unity 4.6.1 with lightparams associated 2. In Unity 5.1, LoadAssetBundles script at Start, downloading and instantiating assetbundle 3. Association of ligthmapping information from Lightparams component
but facing similar issue that, in Unity 5 editor I got assetbundles working correctly but somehow not downloading in web Browser. Only difference is that I had copied all the lightmaps manually in the Unity project folder. I am associating lightmaps after instantiation. It will be great if you can elaborate the necessary steps to get 4.6 lightmapped assetbundles in WebGL Browser.
Your answer
![](https://koobas.hobune.stream/wayback/20220613190923im_/https://answers.unity.com/themes/thub/images/avi.jpg)