Sudden Prefab Size Bloating (2021.3 LTS)

Hello everyone!
We’ve been working hard on polishing the visuals for a number of Towns in our game (Unity 2D / URP), but a recent update from 2020 LTS to 2021.3 LTS has led to a strange prefab size bloating issue that we haven’t been able to find any solutions or hints for! I posted a similar issue on the SPINE (Esoteric Software) forums thinking it was initially an issue with SPINE (third-party animation software), however after more playtesting, experimenting in prefab editing mode, and more, I think it may have to do with Unity (which then has its effect on SPINE)… and so here I am!

Our game has a complex prefab system for managing towns and other environments—each town has a number of NPCs, each NPC being its own prefab variant (of a baseline NPC) that has most of its settings saved to the prefab variant (exceptions being position in the town, etc., which are saved in the town prefab).

When saving an existing Town prefab, the file size of the prefab jumps 30-50x, from pre-update sizes of around 1-5 mb to 50-90 mb now (in one specific case, 30 mb to 600 mb…;w;). I wasn’t sure what the problem was and didn’t know why 1,500,000-10,000,000 lines were being added to the .prefab file when checking the diff for prefabs on GitHub

I’m finding that a prefab’s data’s triangle, position, color, indices etc data are all being saved into the parent prefab (town), and this seems to be the cause of the prefab file size bloat. Within the Town prefab, I’m seeing millions of lines (with the guid corresponding to a prefab) like this:

- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1388]
  value: 463
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1389]
  value: 462
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1390]
  value: 460
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1391]
  value: 461
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1392]
  value: 459
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1393]
  value: 461
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1394]
  value: 460
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1395]
  value: 458
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1396]
  value: 459
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1397]
  value: 460
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1398]
  value: 442
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1399]
  value: 459
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1400]
  value: 458
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1401]
  value: 444
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1402]
  value: 442
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1403]
  value: 458
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1404]
  value: 443
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1405]
  value: 454
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1406]
  value: 457
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1407]
  value: 455
  objectReference: {fileID: 0}
- target: {fileID: 993508108996568647, guid: 59eecd1c5cc9e44bd99528cfa1581e21,
    type: 3}
  propertyPath: m_Triangles.Array.data[1408]
  value: 457
  objectReference: {fileID: 0}

I noticed that this is only bloats the overarching prefab’s size when smaller prefabs (in this case, visuals - trees) are added. Each tree prefab is only 5 kb, yet adding one and saving increases the overall prefab’s size by 1-2 MB.

I’m not sure how reproduction works for this, but it definitely began happening after the update to 2021.3 LTS. Here are some more notes:

  • We’re using URP.
  • All the visual prefabs (the 5 kb ones that bloat the parent by 1-2 MB) are static and contain two or more instances of URP’s Light2D to work with the 2D lighting system we have with.
  • Deleting the visual prefab from the parent prefab reduces the size by 1-2 MB.
  • All visual prefabs are marked as static.
  • The only overridden details for a visual prefab are the in-world position and the sorting layer / order in layer for the Sprite Renderer.

If there’s any other information that I should supply to help make this easier to understand/resolve, please let me know! If this can be resolved, we’ll be able to speed up prefab saving times from the current 1-3 minutes to the original 10-25 seconds…!!

Bump! Is there any more detail needed to draw any ideas as to why this issue is happening?

Another bump!

Hi Jullien, sorry for the late reply. Can you share minimal repro project? Or the files that have bloated so we can investigate what happened? Please add this to a bugreport and mention the case number here.
Thanks.

Do you know what script has the m_Triangles array? If so please add the script here. Seems wrong to generate prefab override for this data.

Hi, apologies for the late follow up! After a lot of testing and experimenting, I think the root cause comes down to overridden properties of the URP Light2D component being serialized/saved in such a way that causes the massive redundant lines to occur. It’s strange because this didn’t happen before our version up from 2020 LTS to 2021 LTS.

Our prefab, which has its size get multiplied is only 2 kb as a default prefab (“LightRay”):

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3229529769903841699
GameObject:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  serializedVersion: 6
  m_Component:
  - component: {fileID: 3888023561761034477}
  - component: {fileID: 8984987226688656336}
  m_Layer: 0
  m_Name: LightRay
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &3888023561761034477
Transform:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 3229529769903841699}
  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
  m_LocalPosition: {x: -6.31, y: 6.79, z: 0}
  m_LocalScale: {x: 4, y: 4, z: 4}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8984987226688656336
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 3229529769903841699}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 073797afb82c5a1438f328866b10b3f0, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  m_LightType: 2
  m_BlendStyleIndex: 0
  m_FalloffIntensity: 0.5
  m_Color: {r: 0.86627805, g: 0.9716981, b: 0.9608571, a: 1}
  m_Intensity: 1
  m_LightVolumeOpacity: 0
  m_ApplyToSortingLayers: ed38399b0000000067f7e282679444fc19fcaf57733e98c1f55a7776410f6aeb49f6dcd2
  m_LightCookieSprite: {fileID: 21300000, guid: fb0337c89564f204e941df1f2bf3e0b0,
    type: 3}
  m_UseNormalMap: 0
  m_LightOrder: 0
  m_AlphaBlendOnOverlap: 0
  m_ShadowIntensity: 0
  m_ShadowVolumeIntensity: 0
  m_PointLightInnerAngle: 360
  m_PointLightOuterAngle: 360
  m_PointLightInnerRadius: 0
  m_PointLightOuterRadius: 1
  m_PointLightDistance: 3
  m_PointLightQuality: 1
  m_ShapeLightParametricSides: 5
  m_ShapeLightParametricAngleOffset: 0
  m_ShapeLightParametricRadius: 1
  m_ShapeLightFalloffSize: 0.5
  m_ShapeLightFalloffOffset: {x: 0, y: 0}
  m_ShapePath:
  - {x: -0.5, y: -0.5, z: 0}
  - {x: 0.5, y: -0.5, z: 0}
  - {x: 0.5, y: 0.5, z: 0}
  - {x: -0.5, y: 0.5, z: 0}

Whereas any adjustments to properties in Light2D seem to produce the a gajillion entries for:

  • m_Triangles.Array (3000+)
  • m_Vertices.Array (1200+) (uv.x, uv.y, color.a, etc.)

I made a copy of the overarching prefab that was 200+ mb and reset the overrides for a number of lights, and the prefab size dropped by 50 mb within 10 minutes of work. However, it doesn’t make sense to me that the lights would punish us (with bloat) for customizing their colors or intensities, and it also probably wouldn’t make sense to make a new prefab for every single overridden light that is prepared.

Because this seems to be more of a (potential) URP issue, would it make more sense to open a new issue on their end of the forums, or is there more we can discuss/troubleshoot in this thread?

Thank you!

PS: Only 2 fields are overridden in the Light2D component, and we acknowledge that probably not all 9 sorting layers should be selected (but modifying that doesn’t affect the prefab bloat).

8925014--1222952--Screen Shot 2023-04-03 at 1.40.26 PM.png

Good info. Does this issue reproduce in a small project? I will take a look at my side as well.

1 Like

This is a 2D/URP bug. Do you mind creating a bug report for it so we can get it tracked?
Just create a new new project on the version of Unity you are using and attach that project with a simple setup with 2D lights.

1 Like

@JulianRice Please provide the case number to the bug here

@Mads-Nyholm Hello! Here’s the case number: CASE IN-38390
Thank you for taking a look at this and letting me know the next steps.

1 Like

Hey! I’ve noted the bug fix has been implemented a while ago, and while reproduction isn’t an issue, the fix applied by Unity doesn’t seem to easily resolve existing issues regarding over-serialization of light/vertex data, meaning that all of the environments we have in our game can’t be easily fixed without rebuilding the entire environment (which isn’t plausible based on our timeline/the scale).

Is there a way the Unity team can implement a fix that also fixes prefabs that have been impacted by this nasty bloating bug? I was able to find a way to bring our largest town/environment from 800 MB to 600 MB, but it’s still too large (and it used to be 20-30 MB before the bloating bug was discovered/released)

Thank you!

Hi Julian

Try resaving all Prefabs. Something like:

using UnityEngine;
using UnityEditor;
public class Example
{
    [MenuItem("Example/Resave Prefabs")]
    static void ResavePrefabs()
    {
        string[] prefabGUIDs = AssetDatabase.FindAssets("t:prefab");
        foreach (string guid in prefabGUIDs)
        {
            var prefabPath = AssetDatabase.GUIDToAssetPath(guid);
            var prefabAssetRoot = AssetDatabase.LoadMainAssetAtPath(prefabPath) as GameObject;
            PrefabUtility.SavePrefabAsset(prefabAssetRoot);
            Debug.Log("Resaved " + prefabPath);
        }
    }
}

Hope this helps

Hi! Thanks for the suggestion. Regardless of how the prefabs are saved (whether from saving while in prefab explorer/mode, or using the editor’s API), the size doesn’t get reduced and the serialized light data remains there. Reimporting and refreshing the assets don’t work either.

This has been stunting a lot of polish we’re trying to apply to our environments because the IDE lags a lot specifically for these 200-600 MB areas, and one save takes a couple minutes (not to mention it makes us require the use of GIt LFS for every push).

I’ll try removing instances of light2D, saving, then adding back the instances of light2D (probably using Undo/CMD-Z) to see if that reduces the overall size, but if you have any other suggestions in the meantime, that would help us greatly!

Thank you!

Were you able to resolve the light issue?

Hi Chris,
I was able to figure out a manual solution to removing the light/bloat issue, but it took many hours to do (20+ for every environment and asset that was broken/bloated). I wasn’t able to 100% clean the prefabs out during the time span, but I was able to remove around 36,000,000 lines of code (around 1 GB of prefab bloat).

This is what I did:
For the environments, prefabs in it that were actually small in size (< 50 kb) but bloated to 2-8 mb+ (40-160x bloat) were resolved by:

  • Adding the prefab again from inspector
  • Copy ALL the values via copy-component + paste-component-values (for whatever was modified)
  • Remove the old/bloated prefab from the inspector
  • Save the environment and note that the environment size drops by 2-4 MB

For the prefabs variants that were large/bloated in size due to their parent prefab being large/bloated, this was tricky:

  • I went into the .prefab file and manually deleted the hundreds of thousands of lines of serialized data saved in the m_Modifications section of the yaml.

  • Note: Before I did this, I went to the upper-most prefab (parent) and removed the Light2D instances that had custom values set, saved the parent, and made sure that the parent’s size was able to drop from megabytes to a few kilobytes.

  • However, doing this doesn’t automatically fix your prefab variants, so I had to do what I outlined in Step 1 (manually deleting the details in m_Modifications)

  • This reduced the bloated prefab size immediately by 99.5%+, and didn’t result in any reimport problems (phew!)

As an end result, I brought down the environment prefab total (all env.) size from 1.4 GB to < 200 MB (7x fixed), and I think I can bring it down even more to < 100 MB if I spent another 20 hours on it, but it’s at a workable state now.

If there was an update on Unity end to automatically sift through and remove these serializations, or a script that the team could prepare to help developers who are in a similar situation as me, that would be amazing. We have been on a busy schedule for preparing for beta/launch, and don’t really have much bandwidth anymore (after the extra time already spent trying to bring the size down to 200 MB) for jumping head-deep back into this. Please let us know your thoughts (if any~) and if there are any updates regarding fixing the bloat in a less tedious process!

Thanks for following up and I hope my solution/process is able to help someone else out!

Hey Julian,

We ran into a similar prefab bloating issue today caused by ProBuilder. While we identified the problem early enough to prevent it from effecting all our prefabs, the already affected prefabs didn’t auto-correct in size. So thank you so much for sharing your clean up solutions — they are going to be very useful for us this week.

Ad Astra,
Jarvis

In 2022.2 we have added functionality to remove all unused overrides from instances. Read more about this feature here: Unity - Manual: Unused Overrides.
Note that you can remove unused overrides for all Prefab instances in a Scene by using the context menu for the Scene in the Hierarchy. For Prefab Variants you have to open them in Prefab Mode and select the “Remove Unused” option in the Overrides window.

1 Like

Can you share what data bloated your Prefabs? Sounds like an issue we need to fix as well.