Search Unity

Problems with instantiating baked prefabs

Discussion in 'Global Illumination' started by GSdev, May 8, 2015.

Thread Status:
Not open for further replies.
  1. AngryMuppet

    AngryMuppet

    Joined:
    Mar 28, 2014
    Posts:
    34
    I'm not 100% sure I understand what you're doing, but it sounds like you might be copying in editor and running and seeing in the profiler that you have batched calls.

    Then at run time you're instantiating prefabs into the scene and seeing that they aren't batching? If that's the case then static batching isn't a run time optimization - you'd need to look at calling http://docs.unity3d.com/ScriptReference/StaticBatchingUtility.Combine.html on your instantiated prefab to get it to batch statically.
     
    febucci likes this.
  2. febucci

    febucci

    Joined:
    Sep 3, 2015
    Posts:
    19
    It worked. Thank you!
     
  3. JigneshKoradiya

    JigneshKoradiya

    Joined:
    Dec 7, 2014
    Posts:
    5
    you can follow this video if you have problem on baking prefeb

     
  4. JigneshKoradiya

    JigneshKoradiya

    Joined:
    Dec 7, 2014
    Posts:
    5

    this will help you:
     
  5. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
  6. LadyR0uge

    LadyR0uge

    Joined:
    Aug 1, 2015
    Posts:
    8
    Hi, I try the first script that @Joachim_Ante posted. I try it with my own project. I got the same result that @AngryMuppet had (all black and white scene), even when I instantiate the prefab in the same scene where I baked the prefab. I then try the script from @JigneshKoradiya and follow the same step like in the video. I get the same result: all black and white.

    I decided to try to work in the test project that @Joachim_Ante provided with the script. I got good result with it. However, I tried to create a new scene within that project and when I drag the two prefabs in the scene and press play, I end up with a similar result than previously.



    I am using Unity 5.1.3f1 at the moment. What could be the cause of the problem?

    Edit: I realise I was still baking with the directional mode. Once I switched it to non directional, it works!
     
    Last edited: Sep 25, 2015
    Airvant and danien like this.
  7. LadyR0uge

    LadyR0uge

    Joined:
    Aug 1, 2015
    Posts:
    8
    What exactly do you mean by manually assign the lightmap snapshot? Do you mean you need to change the Lightmap Snapshot under the Lightmaps tab in Lighting panel? But if you use multiple prefab that were baked in different scene, different LightmapSnapshot file would be generated...


    Edit: I finally understand what you mean by that! However, I was able to make it work without having to replace the file.
     
    Last edited: Sep 25, 2015
    rocket5tim likes this.
  8. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    I have a prefab that has child, then inside that child is the object where i have the PrefabLightmapData, and it completely deleted everything in the prefab except that sub child, and made it the parent (aka the only object), and then automatically saved the prefab... any idea how i can get to not do that? is it if i do too many children? do i need to assign it on the most parent?
     
  9. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    If i look at the lightmapping window, it appears that the lightmaps are being added in that giant list, and if 0 is already filled it will add it to 1, then 2, then 3...... shouldnt it check if its already added in the scene, and not try to add it itself if its already been added to the slot?
     
    Last edited: Oct 3, 2015
  10. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    I started writing code to check if the lightmap is already in there, but its very shotty, HOWEVER, it drastically reduces setpass calls, so that everything uses that 1 lightmap and somehow unity batches it on its own. massive setpass call saving. If someone could write it more elegantly before i do that would be great. also it does not check for existing images, thats an issue, i just stuck it at 0, it would be great if it could check on that.
     
    Last edited: Oct 3, 2015
  11. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    After reviewing my code, i've determined that one way to keep track of both the lightmap and the lightmapIndex, is to create a struct for the lightmapindex which holds its alternate index value.

    or to simply put the lightmap selecter in the RendererInfo (no longer needs to have user select index, instead they select the lightmap itself).

    This is essential to reducing set pass calls.
     
  12. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    Here is the code i have written, it works so far 100% with multiple lightmaps, and keeps track of where the lightmaps are placed, without having to modify much of the code, however i would go back and change the other parts of the code so that i can just use a 2nd struct for the lightmaps and fill them in that way.

    but for now, heres the replacement code

    Code (CSharp):
    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.     [SerializeField]
    16.     RendererInfo[]    m_RendererInfo;
    17.     [SerializeField]
    18.     Texture2D[]     m_Lightmaps;
    19.  
    20.     private bool existsAlready = false;
    21.     private int counter = 0;
    22.     private int[] lightmapArrayOffsetIndex;
    23.  
    24.     void Awake ()
    25.     {
    26.         if (m_RendererInfo == null || m_RendererInfo.Length == 0)
    27.             return;
    28.  
    29.         var lightmaps = LightmapSettings.lightmaps;
    30.         var combinedLightmaps = new LightmapData[lightmaps.Length + m_Lightmaps.Length];
    31.         lightmapArrayOffsetIndex = new int[m_Lightmaps.Length];
    32.  
    33.         for (int i = 0; i < m_Lightmaps.Length; i++)
    34.         {
    35.             existsAlready = false;
    36.  
    37.             for (int j = 0; j < lightmaps.Length; j++)
    38.             {
    39.                 if (m_Lightmaps[i] == lightmaps[j].lightmapFar)
    40.                 {
    41.                     lightmapArrayOffsetIndex[i] = j;
    42.                     existsAlready = true;
    43.                 }
    44.             }
    45.  
    46.             if (!existsAlready)
    47.             {
    48.                 lightmapArrayOffsetIndex[i] = counter + lightmaps.Length;
    49.                 combinedLightmaps[i] = new LightmapData();
    50.                 combinedLightmaps[i].lightmapFar = m_Lightmaps[i];
    51.                 ++counter;
    52.             }
    53.         }
    54.  
    55.         var combinedLightmaps2 = new LightmapData[lightmaps.Length + counter];
    56.         lightmaps.CopyTo(combinedLightmaps2, 0);
    57.  
    58.         if (counter > 0)
    59.         {
    60.             for (int i = 0; i < counter; i++)
    61.             {
    62.                 combinedLightmaps2[i + lightmaps.Length] = new LightmapData();
    63.                 combinedLightmaps2[i + lightmaps.Length].lightmapFar = combinedLightmaps[i].lightmapFar;
    64.             }
    65.         }
    66.  
    67.         ApplyRendererInfo(m_RendererInfo, lightmapArrayOffsetIndex);
    68.  
    69.         LightmapSettings.lightmaps = combinedLightmaps2;
    70.     }
    71.  
    72.  
    73.     static void ApplyRendererInfo (RendererInfo[] infos, int[] arrayOffsetIndex)
    74.     {
    75.         for (int i=0;i<infos.Length;i++)
    76.         {
    77.             var info = infos[i];
    78.             info.renderer.lightmapIndex = arrayOffsetIndex[info.lightmapIndex];
    79.             info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
    80.         }
    81.     }
    82.  
    83. #if UNITY_EDITOR
    84.     [UnityEditor.MenuItem("Assets/Bake Prefab Lightmaps")]
    85.     static void GenerateLightmapInfo ()
    86.     {
    87.         if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
    88.         {
    89.             Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
    90.             return;
    91.         }
    92.         UnityEditor.Lightmapping.Bake();
    93.  
    94.         PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
    95.  
    96.         foreach (var instance in prefabs)
    97.         {
    98.             var gameObject = instance.gameObject;
    99.             var rendererInfos = new List<RendererInfo>();
    100.             var lightmaps = new List<Texture2D>();
    101.          
    102.             GenerateLightmapInfo(gameObject, rendererInfos, lightmaps);
    103.          
    104.             instance.m_RendererInfo = rendererInfos.ToArray();
    105.             instance.m_Lightmaps = lightmaps.ToArray();
    106.  
    107.             var targetPrefab = UnityEditor.PrefabUtility.GetPrefabParent(gameObject) as GameObject;
    108.             if (targetPrefab != null)
    109.             {
    110.                 //UnityEditor.Prefab
    111.                 UnityEditor.PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
    112.             }
    113.         }
    114.     }
    115.  
    116.     static void GenerateLightmapInfo (GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps)
    117.     {
    118.         var renderers = root.GetComponentsInChildren<MeshRenderer>();
    119.         foreach (MeshRenderer renderer in renderers)
    120.         {
    121.             if (renderer.lightmapIndex != -1)
    122.             {
    123.                 RendererInfo info = new RendererInfo();
    124.                 info.renderer = renderer;
    125.                 info.lightmapOffsetScale = renderer.lightmapScaleOffset;
    126.  
    127.                 Texture2D lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
    128.  
    129.                 info.lightmapIndex = lightmaps.IndexOf(lightmap);
    130.                 if (info.lightmapIndex == -1)
    131.                 {
    132.                     info.lightmapIndex = lightmaps.Count;
    133.                     lightmaps.Add(lightmap);
    134.                 }
    135.  
    136.                 rendererInfos.Add(info);
    137.             }
    138.         }
    139.     }
    140. #endif
    141.  
    142. }
     
    Last edited: Oct 3, 2015
    kilosaurus and MihaPro like this.
  13. Kirira

    Kirira

    Joined:
    Apr 23, 2015
    Posts:
    2
    Hi, firstly thanks for the tool.

    I'm having issues with the lightmapped prefabs when instancied with different orientation than the original prefab.
    It looks like the lighting data are blocked on the original rotation and do not follow the prefab like the position.
    I tried to modify the script on the ApplyRendererInfo func to include the prefab orientation on the lightmap index and scale offset info but i'm not finding the right way to do that.

    Any help would be greatly appreciated.

    Regards
     
  14. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    are you changing the prefab's orientation at run time? after its originally been instantiated? Im curious if lightmaps cannot have their positions rotated.

    Just so you know, i have plenty of objects that i've pre set in editor, but then i call staticbatchutility at run time. However all of these prefabs have different orientation from eachother. So thats why i was asking if you were rotating at run time, like letting the user rotate the object, or if your rotated with a script.
     
  15. Kirira

    Kirira

    Joined:
    Apr 23, 2015
    Posts:
    2
    I'm instantiating prefab at original prefab position. After instantiated the prefab I just move and rotate it to a selected target transform. Those who have same orientation than the original prefab are just perfectly lightmapped but those who are rotated with different orientation have lightmapping issues.
    If I rotate (at runtime) my prefab to reach the original orientation, lightmapping issues disappear.

    Regards
     
  16. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    Kirira, i have just tested, and i hate to say this, but it works perfectly on mine, i turned off staticbatchutility, and rotated everything at run time, and it all worked perfectly, no lightmapping issues.

    I put the PrefabLightmapData script on the parent of the prefab, im not sure if that has anything to do with your issue.

    Very sorry, maybe you could post a small sample project and see if it happens in that project too. then i could try and help rip it apart for you. Also it may appear as if the sample works perfectly, but the other project doesnt, sort of situation.

    This is on 5.2? im assuming, since this script hasnt been updated for 5.3.
     
  17. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909


    same here no idea
     
  18. supaworst

    supaworst

    Joined:
    Mar 26, 2012
    Posts:
    45
    I've solved a similar issue on the lightmapped prefab by changing the directional mode to non-directional. It sounds to me strange because i baked my lightmaps in directional mode but now, everything seems to work correctly.

    Now i'm facing another problem: when i spawn my prefab in an empty scene i can't change my ambient lighting, both color and intensity. Any suggestion?
     
  19. JungHwan.Lim

    JungHwan.Lim

    Joined:
    Jan 21, 2014
    Posts:
    3
    Hello. I am using Unity 5.2.1. but I can't use the Terrain Renderer yet.
    Can you tell me when I can use this.?

    And I think this problem can be solved if lightmap info be saved in each instances without saving into prefabs.
    then I think it doesn't need each prefabs should be fixed and committed.
    If it is possible, this problem can be solved in a dimesion of engine.
    thank you :)
     
  20. kilosaurus

    kilosaurus

    Joined:
    Oct 2, 2013
    Posts:
    5
    Concerning the lightmap in prefabs issue, I understand that you unity folks have done it by design. But what I don't understand is why a tool to store lightmaps in prefabs (that works ! an official tool !) is not included in unity 5.

    You make a regression by design and don't implement the way to counterbalance that regression in a tool.
    I dont get it.

    And giving away a partial solution in a forum thread is not a way to go... There is NOTHING in the docs concerning
    prefabs and lightmaps.
     
  21. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    I wanted to chime in about the issues with rotation prefabs, this happens with directional lightmaps for me, which is a shame, i really liked having those, i wish i could rotate prefabs dual lightmapped directional baked objects.
     
  22. NavarioN

    NavarioN

    Joined:
    May 28, 2015
    Posts:
    1
    Hello, could you tell me, how did you exactly solve this problem?


    ------------------------------
    I'm experiencing some issues in runtime with this solution. In editor it looks okay:
    http://i.imgur.com/swiN1So.png

    But when I build it, it looks like this:
    http://i.imgur.com/dArbiuz.png

    So my new object is baked inproperly.

    Can anyone help me with this problem?
     
    Last edited: Nov 20, 2015
  23. LadyR0uge

    LadyR0uge

    Joined:
    Aug 1, 2015
    Posts:
    8

    Have you uncheck "static batcing"?
    And for the snapshot thing, I just did nothing. As long as your snapshot and lightmaps are okay in the baked scene, everything should be fine with the game scene containing the prefabs.
     
  24. allenwp

    allenwp

    Joined:
    Sep 4, 2013
    Posts:
    46
    Hello,

    We're finally porting our mobile VR game over to Unity 5 and have run into a problem "caused" by the LightmapEditorSettings.lockAtlas deprecation and the inability to change a renderer's lightmapIndex and lightmapScaleOffset after StaticBatchingUtility.Combine.

    We are switching lightmaps at runtime. We are also performing a StaticBatchingUtility.Combine at runtime before switching between lightmaps. After performing the StaticBatchingUtility.Combine, we can't seem to change any renderer's lightmapIndex and lightmapScaleOffset properties. Previously with Unity 4, we could simply use use LightmapEditorSettings.lockAtlas = true and remove the need to change the renderer's properties, but with Unity 5 we can no longer lockAtlas.

    Help?

    Here are some more details on our old and new process in case they're helpful:

    With Unity 4, we would run a "UV" baking pass which would determine each renderer's lightmapIndex and lightmapScaleOffset. After this was done, we would use LightmapEditorSettings.lockAtlas = true and then bake the rest of the lightmaps (lights on, lights off, emergency lights, etc.). Then at runtime we would use StaticBatchingUtility.Combine before switching between lightmaps. Because we never needed to change renderer properties at runtime, this worked well.

    With Unity 5, we have been using the method described in this topic to swtich between lightmaps at runtime. Everything is working great until we try to StaticBatchingUtility.Combine and are no longer able to change each renderer's lightmapIndex and lightmapScaleOffset.

    Thanks for your time!
     
    saybor likes this.
  25. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    Sorry, i always change the lightmap just before i call staticbatching utility.
     
  26. latas

    latas

    Joined:
    Oct 9, 2013
    Posts:
    149
    I'm trying to use this script in 5.3.1f1 and I'm not able to add the script, because Unity believes it is an Editor Script. I guess it is an issue with #if UNITY_EDITOR define, but this was working for me in Unity 5.2.X. Any idea?

    Thank you.
     
  27. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    it works if you use the code i pasted several posts back.
     
  28. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Hi,I tried this script though its not giving proper output, the lightmap seems to be messed up ....

    I tried changing line #66 to
    Code (CSharp):
    1.          
    2.        
    3.             info.renderer.lightmapIndex = (info.lightmapIndex*-1 + lightmapOffsetIndex );
    4.  
    5.  
    6.  
    Its now giving proper lightmaps but shadows are not showing at all. its kind of feel like unlit...anyone know whats the problem?
    WIth script disable its giving proper output
     
  29. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    oddly, it seems in unity 5.3.1 it changed the output, you have to manually drag in the lightmap. thats very weird. but if you drag it in and click apply to prefab, it'll save... but its always going to spit out blank when you run the script. i hope a unity dev could shine some light as to why it fills in blankly now. and i check if its null, doesnt seem to matter, just filled in blank.

    Also, I was talking about my code specifically, i cant exactly comment on the original, if you could specify that would help. the original generals a copy of the lightmap in the ram, for every single object. where as mine does not.
     
    idurvesh likes this.
  30. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Thanks for replay stuck at this problem for almost half a day...will revert back to 5.3.0 now.... @Joachim_Ante plz have look into it
     
  31. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Tried with 5.3.0..same happening....I think the lightmaps list is not saving texture2d ...its getting empty when prefab gets store...
     
  32. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
  33. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    mine looks like the bottom one. sorry that 5.3 was not helpful, i was using 5.3 beta f1 prior to 5.3.1 , im guessing it couldve gotten messed up anywhere after 5.2
     
    idurvesh likes this.
  34. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    I reported it as bug.Here is bug report Case 757575
     
  35. bretm

    bretm

    Joined:
    Apr 4, 2015
    Posts:
    1
    I'm having the same issue that a couple of other people reported, i.e. this script all works fine when the game is run in the editor, but not in a build. E.g. when I run it on Android, the lightmaps stored in the PrefabLightmapData aren't showing up. I have several complex prefabs, each created in their own scene and lightmaps precomputed in those scenes and saved into the prefabs using this script. When I create a new scene, add some prefabs to it, and run it in the editor it looks fine--the baked lighting shows up. When I build & run, the baked lighting doesn't show up.

    Any idea what I'm missing?

    Edit:

    Initially I was getting no baked lighting at all. Everything in the dynamic scene just had flat lights with no ambient occlusion, etc. When I started to mess with the "lightmap snapshot" I started to get different behavior. My prefabs are "tiles" with various scenery and other props on them. The lighting now looks correct for the main tile base object in each prefab, but the other objects in each prefab are showing the wrong baked lighting, either having the wrong texture coordinates or are pulling from the wrong lightmap atlas altogether. So it's sort of working, but mostly not.

    Since the lightmap snapshot was having an effect on the behavior, I tried putting all the prefabs into one scene and baking them all together and then using that scene's lightmap snapshot as the snapshot used by the dynamic scene, but that produced the same result. The largest object in each prefab is showing the right lighting and the other objects are pulling light data from the wrong places. It's really weird.
     
    Last edited: Jan 2, 2016
  36. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    bretm i have a similar issue like that, except only when using Dual Lightmaps as my baking target, it works in emulation es2 but on device it wouldnt properly fallback to single lightmap, for some reason.
     
  37. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    I'm using 5.3.1f1, and I noticed the texture2D fields get wiped whenever PrefabUnity.ReplacePrefab is called. I haven't figured out a way of getting it to not wipe the texture2D fields yet.
     
  38. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Yes same here, I reported bug for it @ case #757575
     
  39. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    The problem is that they bundled all the lightmaps into one asset called LightingDataAsset. Because of this the Prefab.ReplacePrefab is not happy about referencing an individual lightmap. I created a work around for it. While it seems to show the lightmaps at runtime, you cannot see the lightmap in the Editor. I created a new folder path "Asset/Resources/Lightmaps" to save the prefab lightmaps.

    Updated to most current version:
    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using UnityEditor;
    3. #endif
    4. using UnityEngine;
    5. using System.Collections.Generic;
    6. public class PrefabLightmapData : MonoBehaviour
    7. {
    8.     [System.Serializable]
    9.     struct RendererInfo
    10.     {
    11.         public Renderer renderer;
    12.         public int lightmapIndex;
    13.         public Vector4 lightmapOffsetScale;
    14.     }
    15.     [SerializeField]
    16.     RendererInfo[] m_RendererInfo;
    17.     [SerializeField]
    18.     Texture2D[] m_Lightmaps;
    19.     [SerializeField]
    20.     Texture2D[] m_Lightmaps2;
    21.     const string LIGHTMAP_RESOURCE_PATH = "Assets/Resources/Lightmaps/";
    22.     [System.Serializable]
    23.     struct Texture2D_Remap
    24.     {
    25.         public int originalLightmapIndex;
    26.         public Texture2D originalLightmap;
    27.         public Texture2D lightmap;
    28.         public Texture2D lightmap2;
    29.     }
    30.     static List<Texture2D_Remap> sceneLightmaps = new List<Texture2D_Remap>();
    31.     void Awake()
    32.     {
    33.         ApplyLightmaps(m_RendererInfo, m_Lightmaps, m_Lightmaps2);
    34.     }
    35.     static void ApplyLightmaps(RendererInfo[] rendererInfo, Texture2D[] lightmaps, Texture2D[] lightmaps2)
    36.     {
    37.         bool existsAlready = false;
    38.         int counter = 0;
    39.         int[] lightmapArrayOffsetIndex;
    40.         if (rendererInfo == null || rendererInfo.Length == 0)
    41.             return;
    42.         var settingslightmaps = LightmapSettings.lightmaps;
    43.         var combinedLightmaps = new List<LightmapData>();
    44.         lightmapArrayOffsetIndex = new int[lightmaps.Length];
    45.         for (int i = 0; i < lightmaps.Length; i++)
    46.         {
    47.             existsAlready = false;
    48.             for (int j = 0; j < settingslightmaps.Length; j++)
    49.             {
    50.                 if (lightmaps[i] == settingslightmaps[j].lightmapFar)
    51.                 {
    52.                     lightmapArrayOffsetIndex[i] = j;
    53.                     existsAlready = true;
    54.                 }
    55.             }
    56.             if (!existsAlready)
    57.             {
    58.                 lightmapArrayOffsetIndex[i] = counter + settingslightmaps.Length;
    59.                 var newLightmapData = new LightmapData();
    60.                 newLightmapData.lightmapFar = lightmaps[i];
    61.                 newLightmapData.lightmapNear = lightmaps2[i];
    62.                 combinedLightmaps.Add(newLightmapData);
    63.                 ++counter;
    64.             }
    65.         }
    66.         var combinedLightmaps2 = new LightmapData[settingslightmaps.Length + counter];
    67.         settingslightmaps.CopyTo(combinedLightmaps2, 0);
    68.         if (counter > 0)
    69.         {
    70.             for (int i = 0; i < combinedLightmaps.Count; i++)
    71.             {
    72.                 combinedLightmaps2[i + settingslightmaps.Length] = new LightmapData();
    73.                 combinedLightmaps2[i + settingslightmaps.Length].lightmapFar = combinedLightmaps[i].lightmapFar;
    74.                 combinedLightmaps2[i + settingslightmaps.Length].lightmapNear = combinedLightmaps[i].lightmapNear;
    75.             }
    76.         }
    77.         ApplyRendererInfo(rendererInfo, lightmapArrayOffsetIndex);
    78.         LightmapSettings.lightmaps = combinedLightmaps2;
    79.     }
    80.     static void ApplyRendererInfo(RendererInfo[] infos, int[] arrayOffsetIndex)
    81.     {
    82.         for (int i = 0; i < infos.Length; i++)
    83.         {
    84.             var info = infos[i];
    85.             info.renderer.lightmapIndex = arrayOffsetIndex[info.lightmapIndex];
    86.             info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
    87.         }
    88.     }
    89. #if UNITY_EDITOR
    90.     [MenuItem("Assets/Update Scene with Prefab Lightmaps")]
    91.     static void UpdateLightmaps()
    92.     {
    93.         PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
    94.         foreach (var instance in prefabs)
    95.         {
    96.             ApplyLightmaps(instance.m_RendererInfo, instance.m_Lightmaps, instance.m_Lightmaps2);
    97.         }
    98.         Debug.Log("Prefab lightmaps updated");
    99.     }
    100.     [MenuItem("Assets/Bake Prefab Lightmaps")]
    101.     static void GenerateLightmapInfo()
    102.     {
    103.         Debug.ClearDeveloperConsole();
    104.         if (Lightmapping.giWorkflowMode != Lightmapping.GIWorkflowMode.OnDemand)
    105.         {
    106.             Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
    107.             return;
    108.         }
    109.         Lightmapping.Bake();
    110.         sceneLightmaps = new List<Texture2D_Remap>();
    111.         var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
    112.         var resourcePath = LIGHTMAP_RESOURCE_PATH + scene.name;
    113.         var scenePath = System.IO.Path.GetDirectoryName(scene.path) + "/" + scene.name + "/";
    114.         PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
    115.         foreach (var instance in prefabs)
    116.         {
    117.             var gameObject = instance.gameObject;
    118.             var rendererInfos = new List<RendererInfo>();
    119.             var lightmaps = new List<Texture2D>();
    120.             var lightmaps2 = new List<Texture2D>();
    121.             GenerateLightmapInfo(scenePath, resourcePath, gameObject, rendererInfos, lightmaps, lightmaps2);
    122.             instance.m_RendererInfo = rendererInfos.ToArray();
    123.             instance.m_Lightmaps = lightmaps.ToArray();
    124.             instance.m_Lightmaps2 = lightmaps2.ToArray();
    125.             var targetPrefab = PrefabUtility.GetPrefabParent(gameObject) as GameObject;
    126.             if (targetPrefab != null)
    127.             {
    128.                 //Prefab
    129.                 PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
    130.             }
    131.             ApplyLightmaps(instance.m_RendererInfo, instance.m_Lightmaps, instance.m_Lightmaps2);
    132.         }
    133.         Debug.Log("Update to prefab lightmaps finished");
    134.     }
    135.     static void GenerateLightmapInfo(string scenePath, string resourcePath, GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps, List<Texture2D> lightmaps2)
    136.     {
    137.         var renderers = root.GetComponentsInChildren<MeshRenderer>();
    138.         foreach (MeshRenderer renderer in renderers)
    139.         {
    140.             if (renderer.lightmapIndex != -1)
    141.             {
    142.                 RendererInfo info = new RendererInfo();
    143.                 info.renderer = renderer;
    144.                 info.lightmapOffsetScale = renderer.lightmapScaleOffset;
    145.                 Texture2D lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
    146.                 Texture2D lightmap2 = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapNear;
    147.                 int sceneLightmapIndex = AddLightmap(scenePath, resourcePath, renderer.lightmapIndex, lightmap, lightmap2);
    148.                 info.lightmapIndex = lightmaps.IndexOf(sceneLightmaps[sceneLightmapIndex].lightmap);
    149.                 if (info.lightmapIndex == -1)
    150.                 {
    151.                     info.lightmapIndex = lightmaps.Count;
    152.                     lightmaps.Add(sceneLightmaps[sceneLightmapIndex].lightmap);
    153.                     lightmaps2.Add(sceneLightmaps[sceneLightmapIndex].lightmap2);
    154.                 }
    155.                 rendererInfos.Add(info);
    156.             }
    157.         }
    158.     }
    159.     static int AddLightmap(string scenePath, string resourcePath, int originalLightmapIndex, Texture2D lightmap, Texture2D lightmap2)
    160.     {
    161.         int newIndex = -1;
    162.         for (int i = 0; i < sceneLightmaps.Count; i++)
    163.         {
    164.             if (sceneLightmaps[i].originalLightmapIndex == originalLightmapIndex)
    165.             {
    166.                 return i;
    167.             }
    168.         }
    169.         if (newIndex == -1)
    170.         {
    171.             var lightmap_Remap = new Texture2D_Remap();
    172.             lightmap_Remap.originalLightmapIndex = originalLightmapIndex;
    173.             lightmap_Remap.originalLightmap = lightmap;
    174.             var filename = scenePath + "Lightmap-" + originalLightmapIndex;
    175.             lightmap_Remap.lightmap = GetLightmapAsset(filename + "_comp_light.exr", resourcePath + "_light", originalLightmapIndex, lightmap);
    176.             if (lightmap2 != null)
    177.             {
    178.                 lightmap_Remap.lightmap2 = GetLightmapAsset(filename + "_comp_dir.exr", resourcePath + "_dir", originalLightmapIndex, lightmap2);
    179.             }
    180.             sceneLightmaps.Add(lightmap_Remap);
    181.             newIndex = sceneLightmaps.Count - 1;
    182.         }
    183.         return newIndex;
    184.     }
    185.     static Texture2D GetLightmapAsset(string filename, string resourcePath, int originalLightmapIndex, Texture2D lightmap)
    186.     {
    187.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    188.         var importer = AssetImporter.GetAtPath(filename) as TextureImporter;
    189.         importer.isReadable = true;
    190.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    191.         var assetLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(filename);
    192.         var assetPath = resourcePath + "-" + originalLightmapIndex + ".asset";
    193.         var newLightmap = Instantiate<Texture2D>(assetLightmap);
    194.         AssetDatabase.CreateAsset(newLightmap, assetPath);
    195.         newLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
    196.         importer.isReadable = false;
    197.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    198.         return newLightmap;
    199.     }
    200. #endif
    201. }
    202.  
     
    Last edited: Jan 11, 2016
  40. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Thanks much for script ,its do finding right lightmap now..kudos...., though its providing blackness after applying lightmap which was not the case previously or used without script...
     
  41. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    It's more of a work around for new bug in 5.3.1f pertaining to the access of the lightmap data by the PrefabUtility API. It's black in the Editor because the prefabs no longer reference the lightmap inside the LightingDataAsset. The editor is not aware of the new lightmap. At runtime it adds the new prefab lightmaps to the scene. At least for me, it's visible at runtime.

    Note: you also need to create "Assets/Resources/Lightmaps" folder in your project.
     
  42. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Yes tried in play mode, still getting blackness ,
    http://imgur.com/NmF1kBY


    Here is screenshot in editor, the one on left taking lightmap properly as its not from script, whereas the one in right is taking lightmapps from script,
    http://imgur.com/ahE4Whz
     
  43. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    Looks like the lightmaps are misaligned. Does it have more than one lightmap on your prefab?
     
  44. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Yes, there are two lightmaps
     
  45. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    I managed to reproduce the multi-lightmap bug. I'll have to debug it more.
     
    Last edited: Jan 3, 2016
  46. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
    Yes plz, I tried that script, its showing properly in Editor Play but not on Actual build....great work so far...
     
  47. tripknotix

    tripknotix

    Joined:
    Apr 21, 2011
    Posts:
    744
    centripetal dont forget to take a look at my script, it supports multiple lightmaps, and does not duplicate the lightmap, which the original did.
     
  48. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    have in my revision. However, I'm having another bug with duplicate prefabs I'm working on resolving
     
  49. idurvesh

    idurvesh

    Joined:
    Jun 9, 2014
    Posts:
    495
  50. Centripetal

    Centripetal

    Joined:
    May 31, 2013
    Posts:
    96
    Here is my next attempt below. I based it on @tripknotix 's code which supports multiple lightmaps per prefab. I added code to extract the lightmaps from the LightmapDataAsset file into separate lightmap files in a resource folder at "Asset/Resources/Lightmaps" (Make sure that directory exists in your project). The original lightmaps outside of the LightmapDataAsset file are intermediate files and might not be included in your project's build. Since the new lightmap files are in a resource folder Unity is guaranteed to include them in your build (since your prefabs may not be in any scene initially). I also added another menu item at Assets->Update Scene with Prefab Lightmaps. This will allow you to update the lightmap in the Editor without running the project. When building the prefab lightmaps, this is automatically called, but if you make duplicate of a prefab, it'll appear black until this is called manually (Because the Editor is unaware of it's mapping to the new lightmaps). If anybody encounters an error with this script, please include information like the line number and error message. Thanks!

    Updated to most current version:
    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using UnityEditor;
    3. #endif
    4. using UnityEngine;
    5. using System.Collections.Generic;
    6. public class PrefabLightmapData : MonoBehaviour
    7. {
    8.     [System.Serializable]
    9.     struct RendererInfo
    10.     {
    11.         public Renderer renderer;
    12.         public int lightmapIndex;
    13.         public Vector4 lightmapOffsetScale;
    14.     }
    15.     [SerializeField]
    16.     RendererInfo[] m_RendererInfo;
    17.     [SerializeField]
    18.     Texture2D[] m_Lightmaps;
    19.     [SerializeField]
    20.     Texture2D[] m_Lightmaps2;
    21.     const string LIGHTMAP_RESOURCE_PATH = "Assets/Resources/Lightmaps/";
    22.     [System.Serializable]
    23.     struct Texture2D_Remap
    24.     {
    25.         public int originalLightmapIndex;
    26.         public Texture2D originalLightmap;
    27.         public Texture2D lightmap;
    28.         public Texture2D lightmap2;
    29.     }
    30.     static List<Texture2D_Remap> sceneLightmaps = new List<Texture2D_Remap>();
    31.     void Awake()
    32.     {
    33.         ApplyLightmaps(m_RendererInfo, m_Lightmaps, m_Lightmaps2);
    34.     }
    35.     static void ApplyLightmaps(RendererInfo[] rendererInfo, Texture2D[] lightmaps, Texture2D[] lightmaps2)
    36.     {
    37.         bool existsAlready = false;
    38.         int counter = 0;
    39.         int[] lightmapArrayOffsetIndex;
    40.         if (rendererInfo == null || rendererInfo.Length == 0)
    41.             return;
    42.         var settingslightmaps = LightmapSettings.lightmaps;
    43.         var combinedLightmaps = new List<LightmapData>();
    44.         lightmapArrayOffsetIndex = new int[lightmaps.Length];
    45.         for (int i = 0; i < lightmaps.Length; i++)
    46.         {
    47.             existsAlready = false;
    48.             for (int j = 0; j < settingslightmaps.Length; j++)
    49.             {
    50.                 if (lightmaps[i] == settingslightmaps[j].lightmapFar)
    51.                 {
    52.                     lightmapArrayOffsetIndex[i] = j;
    53.                     existsAlready = true;
    54.                 }
    55.             }
    56.             if (!existsAlready)
    57.             {
    58.                 lightmapArrayOffsetIndex[i] = counter + settingslightmaps.Length;
    59.                 var newLightmapData = new LightmapData();
    60.                 newLightmapData.lightmapFar = lightmaps[i];
    61.                 newLightmapData.lightmapNear = lightmaps2[i];
    62.                 combinedLightmaps.Add(newLightmapData);
    63.                 ++counter;
    64.             }
    65.         }
    66.         var combinedLightmaps2 = new LightmapData[settingslightmaps.Length + counter];
    67.         settingslightmaps.CopyTo(combinedLightmaps2, 0);
    68.         if (counter > 0)
    69.         {
    70.             for (int i = 0; i < combinedLightmaps.Count; i++)
    71.             {
    72.                 combinedLightmaps2[i + settingslightmaps.Length] = new LightmapData();
    73.                 combinedLightmaps2[i + settingslightmaps.Length].lightmapFar = combinedLightmaps[i].lightmapFar;
    74.                 combinedLightmaps2[i + settingslightmaps.Length].lightmapNear = combinedLightmaps[i].lightmapNear;
    75.             }
    76.         }
    77.         ApplyRendererInfo(rendererInfo, lightmapArrayOffsetIndex);
    78.         LightmapSettings.lightmaps = combinedLightmaps2;
    79.     }
    80.     static void ApplyRendererInfo(RendererInfo[] infos, int[] arrayOffsetIndex)
    81.     {
    82.         for (int i = 0; i < infos.Length; i++)
    83.         {
    84.             var info = infos[i];
    85.             info.renderer.lightmapIndex = arrayOffsetIndex[info.lightmapIndex];
    86.             info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
    87.         }
    88.     }
    89. #if UNITY_EDITOR
    90.     [MenuItem("Assets/Update Scene with Prefab Lightmaps")]
    91.     static void UpdateLightmaps()
    92.     {
    93.         PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
    94.         foreach (var instance in prefabs)
    95.         {
    96.             ApplyLightmaps(instance.m_RendererInfo, instance.m_Lightmaps, instance.m_Lightmaps2);
    97.         }
    98.         Debug.Log("Prefab lightmaps updated");
    99.     }
    100.     [MenuItem("Assets/Bake Prefab Lightmaps")]
    101.     static void GenerateLightmapInfo()
    102.     {
    103.         Debug.ClearDeveloperConsole();
    104.         if (Lightmapping.giWorkflowMode != Lightmapping.GIWorkflowMode.OnDemand)
    105.         {
    106.             Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
    107.             return;
    108.         }
    109.         Lightmapping.Bake();
    110.         sceneLightmaps = new List<Texture2D_Remap>();
    111.         var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
    112.         var resourcePath = LIGHTMAP_RESOURCE_PATH + scene.name;
    113.         var scenePath = System.IO.Path.GetDirectoryName(scene.path) + "/" + scene.name + "/";
    114.         PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
    115.         foreach (var instance in prefabs)
    116.         {
    117.             var gameObject = instance.gameObject;
    118.             var rendererInfos = new List<RendererInfo>();
    119.             var lightmaps = new List<Texture2D>();
    120.             var lightmaps2 = new List<Texture2D>();
    121.             GenerateLightmapInfo(scenePath, resourcePath, gameObject, rendererInfos, lightmaps, lightmaps2);
    122.             instance.m_RendererInfo = rendererInfos.ToArray();
    123.             instance.m_Lightmaps = lightmaps.ToArray();
    124.             instance.m_Lightmaps2 = lightmaps2.ToArray();
    125.             var targetPrefab = PrefabUtility.GetPrefabParent(gameObject) as GameObject;
    126.             if (targetPrefab != null)
    127.             {
    128.                 //Prefab
    129.                 PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
    130.             }
    131.             ApplyLightmaps(instance.m_RendererInfo, instance.m_Lightmaps, instance.m_Lightmaps2);
    132.         }
    133.         Debug.Log("Update to prefab lightmaps finished");
    134.     }
    135.     static void GenerateLightmapInfo(string scenePath, string resourcePath, GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps, List<Texture2D> lightmaps2)
    136.     {
    137.         var renderers = root.GetComponentsInChildren<MeshRenderer>();
    138.         foreach (MeshRenderer renderer in renderers)
    139.         {
    140.             if (renderer.lightmapIndex != -1)
    141.             {
    142.                 RendererInfo info = new RendererInfo();
    143.                 info.renderer = renderer;
    144.                 info.lightmapOffsetScale = renderer.lightmapScaleOffset;
    145.                 Texture2D lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
    146.                 Texture2D lightmap2 = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapNear;
    147.                 int sceneLightmapIndex = AddLightmap(scenePath, resourcePath, renderer.lightmapIndex, lightmap, lightmap2);
    148.                 info.lightmapIndex = lightmaps.IndexOf(sceneLightmaps[sceneLightmapIndex].lightmap);
    149.                 if (info.lightmapIndex == -1)
    150.                 {
    151.                     info.lightmapIndex = lightmaps.Count;
    152.                     lightmaps.Add(sceneLightmaps[sceneLightmapIndex].lightmap);
    153.                     lightmaps2.Add(sceneLightmaps[sceneLightmapIndex].lightmap2);
    154.                 }
    155.                 rendererInfos.Add(info);
    156.             }
    157.         }
    158.     }
    159.     static int AddLightmap(string scenePath, string resourcePath, int originalLightmapIndex, Texture2D lightmap, Texture2D lightmap2)
    160.     {
    161.         int newIndex = -1;
    162.         for (int i = 0; i < sceneLightmaps.Count; i++)
    163.         {
    164.             if (sceneLightmaps[i].originalLightmapIndex == originalLightmapIndex)
    165.             {
    166.                 return i;
    167.             }
    168.         }
    169.         if (newIndex == -1)
    170.         {
    171.             var lightmap_Remap = new Texture2D_Remap();
    172.             lightmap_Remap.originalLightmapIndex = originalLightmapIndex;
    173.             lightmap_Remap.originalLightmap = lightmap;
    174.             var filename = scenePath + "Lightmap-" + originalLightmapIndex;
    175.             lightmap_Remap.lightmap = GetLightmapAsset(filename + "_comp_light.exr", resourcePath + "_light", originalLightmapIndex, lightmap);
    176.             if (lightmap2 != null)
    177.             {
    178.                 lightmap_Remap.lightmap2 = GetLightmapAsset(filename + "_comp_dir.exr", resourcePath + "_dir", originalLightmapIndex, lightmap2);
    179.             }
    180.             sceneLightmaps.Add(lightmap_Remap);
    181.             newIndex = sceneLightmaps.Count - 1;
    182.         }
    183.         return newIndex;
    184.     }
    185.     static Texture2D GetLightmapAsset(string filename, string resourcePath, int originalLightmapIndex, Texture2D lightmap)
    186.     {
    187.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    188.         var importer = AssetImporter.GetAtPath(filename) as TextureImporter;
    189.         importer.isReadable = true;
    190.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    191.         var assetLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(filename);
    192.         var assetPath = resourcePath + "-" + originalLightmapIndex + ".asset";
    193.         var newLightmap = Instantiate<Texture2D>(assetLightmap);
    194.         AssetDatabase.CreateAsset(newLightmap, assetPath);
    195.         newLightmap = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
    196.         importer.isReadable = false;
    197.         AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
    198.         return newLightmap;
    199.     }
    200. #endif
    201. }
    202.  
     
    Last edited: Jan 11, 2016
Thread Status:
Not open for further replies.