OnPostprocessModel can no longer edit meshes with Read/Write set to false (Worked in b7)

In 2020.1b7 and prior, I was able to edit incoming meshes with OnPostprocessModel by accessing the sharedMesh on the MeshFilter of the Prefab.

I have some code that converts incoming Mesh colors into linear space, the function looks like this:

    private void OnPostprocessModel(GameObject g)
    {
        HashSet<Mesh> processed = new HashSet<Mesh>();
        foreach (var mesh in g.GetComponentsInChildren<MeshFilter>().Select(a => a.sharedMesh))
        {
            if (processed.Contains(mesh)) return;
           
            processed.Add(mesh);
            mesh.name += " [Linear]";
            mesh.colors = mesh.colors.Select(a => a.linear).ToArray();
        }
    }

This worked in 2020.1b7 and prior. I did not need to set meshes to read/write enabled. This is intended. I dont want these meshes to be read/write enabled at runtime. I only want to modify the mesh on import.

I just updated to 2020.1b12 and now my meshes wont import. I get the following error:

Not allowed to access colors on mesh 'MyMesh [Linear]' (isReadable is false; Read/Write must be enabled in import settings)
UnityEngine.Mesh:get_colors()
ModelLinearCorrection:OnPostprocessModel(GameObject)

Note this did not happen in b7 and prior.

This is the only way I have found to modify mesh on import. If this change is intended, there is no longer any way to edit meshes during Edit time without setting them to read/write enabled for runtime purposes. So I am hoping this is just a regression and will be fixed! And if not, I hope there is a ‘proper’ way to edit meshes at ‘edit time’ without enabling read/write for runtime.

1 Like

This happens when reading from textures as well, our texture batcher reads from them at edit time and now it breaks.
We have to mark them as read/write, then run the game in the editor, then run the scripts, then stop play mode, then turn off read/write.
Very broken.

1 Like

I have the same problem in 2019.4.0 and 2019.4.1 when trying to modify Meshes in OnPostprocessModel

1 Like

Found this in the Unity 2020.1.0b13 release notes:

Thanks for pointing that out!

What about 2019.4.x though? No mention there or in 2019.3.x’s release notes, yet it broke some time after 2019.3.7 (see #3). The new method is definitely missing in 2019.4.1.

I can’t find anything “AcquireReadOnlyMeshData” related in the public issue track (link), so Unity staff would be needed to answer if a bugfix is planned for 2019.4.

@LeonhardP

Looks like instances of this issue: Unity Issue Tracker - Mesh.GetUVs returns canAccess = false when the mesh is Instantiated / Cloned

Fix is in 20.2a16 and on it’s way to 19.4 and 20.1.

2 Likes

Hey thanks for looking in to this! Just to clarify, this fix will allow us to both read and write into the Mesh instance being imported?

I’m not just interested in reading data, I also need to write data into the imported mesh. I think we got a little off track here and seem to only be focusing on the read aspect. :slight_smile:

The fix is restoring the original behaviour.

1 Like

What about the same issue for texture read/write?

No, the fix is specific to meshes. If you’re experiencing issues on that end, it would be great if you could submit a bug report with reproduction steps. It doesn’t look like this is a known issue.

Bug reporter just crashes, if it gets as far as loading then it always complains the description is not long enough and I end up having to fill it with lorem ipsum.

Here is a full reproduction script, it’s used for a crude atlas generator.
Assign textures, watch it fail to read them in the editor, even with read/write on.
You have to enter playmode for this to run and you have to have read/write on.
It should work at edit time without read/write on.

using System.IO;
using UnityEngine;

[CreateAssetMenu(fileName = "AtlasCreator", menuName = "Game/AtlasCreator", order = 1)]
public class AtlasCreator : ScriptableObject
{
    public Texture2D[] sprites;

    [Header("Settings")]
    public int size = 2048;
    public int tileSize = 32;
    public int tilesX = 12;
    public int tilesY = 16;
    public string atlasName = "GroundAtlas";

    [ContextMenu("CreateAtlas")]
    public void CreateAtlas()
    {
        var x = 0;
        var y = 0;

        var targetTexture = new Texture2D(size, size, TextureFormat.RGBA32, false);

        for (int i = 0; i < sprites.Length; i ++)
        {
            for (int yy = 0; yy < tilesX; yy += 2)
            {
                for (int xx = 0; xx < tilesY; xx += 2 )
                {
                    var pixels = sprites[i].GetPixels(xx * tileSize, yy * tileSize, tileSize, tileSize);
                    targetTexture.SetPixels(x * tileSize, targetTexture.height - (y+1) * tileSize, tileSize, tileSize, pixels);

                    x++;
                    if (x >= size / tileSize)
                    {
                        x = 0;
                        y++;
                    }
                }
            }
        }

        File.WriteAllBytes($"{Application.dataPath}/Game/Ground/{atlasName}.png", targetTexture.EncodeToPNG());
    }
}

Hello SevenPointRed! I’ve managed to make a repro project in 2020.1.0b13, but was unable to reproduce the issue. While it does seem that Atlas operation doesn’t work without having Read/Write enabled on a texture, the same behaviour is present in 2018.4 as well, so it’s not a regression.
After setting Read/Write enabled on the textures, I was able to create the atlas in both Editor and play mode so it might be that the issue got fixed in later 2020.1 versions, or there is more to the bug that just that. I have attached my project.

6039761–652652–AtlasReadWrite.rar (2.13 MB)

Thanks for checking, that’s odd as it always worked for us in previous 2018 versions, though we never touched the latest 2018.4, I don’t remember the last version we used. I will check through git as well, im sure we had some versions of 2019 where it worked.