Continued frustration with read only assets

Hi,

Just encountering yet another read only asset issue, this time with the following:

“UnityException: Texture ‘Default-ParticleSystem’ is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.”

If someone could point me in the right direction of how I can fix this, that’d be terrific.

Can I please ask more broadly, is there a reason why the PolySpatial team didn’t just opt for defaulting to read/write on all textures everywhere? These read only settings issues with various asset types and technologies (like TextMeshPro) on the surface at least, seem like a class of problem that hasn’t needed to exist.

Thanks in advance.

UnityException: Texture ‘Default-ParticleSystem’ is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.
at UnityEngine.Texture2D.GetRawTextureData[T] () [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.ConversionHelpers.GetRawTextureData (UnityEngine.Texture2D tex2d, Unity.Collections.Allocator allocator, UnityEngine.Experimental.Rendering.GraphicsFormat& graphicsFormat) [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.ConversionHelpers.ToPolySpatialTextureData (UnityEngine.Texture2D tex2d, System.Action`2[T1,T2] postConversionCallback) [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.LocalAssetManager.SendTextureAssetChanged (Unity.PolySpatial.Internals.PolySpatialAssetID assetID, UnityEngine.Object unityTexture, System.Boolean allowNativeTextures) [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.LocalAssetManager.ProcessChanges () [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.PolySpatialUnitySimulation.Update () [0x00000] in <00000000000000000000000000000000>:0
at Unity.PolySpatial.Internals.PolySpatialCore.PolySpatialAfterLateUpdate () [0x00000] in <00000000000000000000000000000000>:0
HWLogging.Unity.LogSystem:LogException(LogLevel, String, Exception, Object)
UnityEngine.Debug:CallOverridenDebugHandler(Exception, Object)

Please note this is blocking us from being able to upgrade from 0.6.3 to 0.7.1.

Expand the “Advanced” section of your Texture and turn on “Read/Write enabled”.
Enable the Read/Write toggle also on the atlas if you’re using any.

1 Like

Thanks, I’m aware of how to fix this for a regular texture, the problem is, it’s with one of Unity’s embedded textures, “Default-ParticleSystem”, and so far it appears as though we’re not loading a particle system that uses it. If we can find the particle system that uses this, we’ll replace its texture with one that’s read/write, but the overall problem is, this is a problem that shouldn’t need to exist, especially with Unity defaults like this.

Beyond this issue, which is blocking us at the moment, is all the times we’ve lost time to having to track down these individual read/write flags, when it appears as though it could be addressed on a systemic level by PolySpatial, so that we’re not continually taxed with these issues. We had one with

So you telling me the defaut sprite used in the particle system is the one creating this issue? If that’s the case you should be able to change it in the renderer area of your particle.

Try to find the particle material in your project folder (named “ParticlesUnlit” usually),Right Click and do a Find Reference In Scene should show you all the Particle System using it in your scene.

Thank you. We have a rather large project that’s been developed over several years of content, so it can be quite difficult trying to track down these isolated instances that cause the overall runtime to crash.

I appreciate you helping me with this instance of the problem, but would also like to keep the broader question going on this thread, which is, why is it necessary for us to keep having to play whack-a-whole with every texture, be it ours, or a built in one, when at least, it appears to me naively, that the runtime should just assume that all textures are read/write, given that it’s a platform with unified and shared memory? It would save us so much time and frustration, if either the runtime didn’t crash with an exception in these cases, and just make the assumption that all textures are read/write. I’d love to know from someone on the PolySpatial team whether this is feasible as a change, or whether there’s a good reason why we keep having to step over these little land mines of things that could otherwise be solved with a virtual ‘stroke of the pen’ on the system side. And even if there’s a good reason why default read/write can’t be assumed, why it can’t at least be fixed for all Unity systems, like built in assets, TextMeshPro etc.

The good thing about the Discussions as opposed to bug reports, is that I can pose these questions where, the team learns of the issues that are needlessly consuming the time of development teams, and where little fixes or improvements (such as logging the names of things when there’s a crash when a tracked child is parented to a non-tracked object) can be made that benefit everybody by not taxing everyone’s time needlessly.

Thanks in advance.

I saw Unity devs telling they will make the read/write true by default, I hope they implemented it on last updates. I don’t know why they didn’t make it that way initialy, I guess it’s related to a security issues, no other clue…

Have a look on the second answer of this thread. Hope it helps.

It’s more of a memory issue: textures that allow read/write need to be stored in CPU memory.

It may be appropriate for us to make all textures read/write enabled for PolySpatial, but if not/until then, you should be able to use an AssetPostprocessor to do it for all textures in your project. I believe it would look something like this:

using UnityEditor;
using UnityEngine;

public class ReadableTexturePostprocessor : AssetPostprocessor
{
    bool m_WasReadable;

    void OnPreprocessTexture()
    {
        var textureImporter = (TextureImporter)assetImporter;
        m_WasReadable = textureImporter.isReadable;
        if (!m_WasReadable)
            textureImporter.isReadable = true;
    }

    void OnPostprocessTexture(Texture2D texture)
    {
        if (!m_WasReadable)
        {
            var textureImporter = (TextureImporter)assetImporter;
            textureImporter.isReadable = false;

            // Don't reserialize the importer, since the change was only temporary.
            EditorUtility.ClearDirty(textureImporter);
        }
    }
}

Thank you, but I believe my issue here is that I’m unable to use this technique for the “Default-ParticleSystem” texture, and I haven’t yet found what’s referencing it (I’ll report back once I catch the issue). I hacked the Xcode project to catch the issue, and was able to call “return” inside the ProcessChanges method on the C++ side (just for debugging purposes) if ever it encountered that texture, and our game started running again, so it’s that one for sure.

We had the same with the texture that TextMeshPro generates, but luckily were able to set it to not regenerate the texture (Clear Dynamic Data), but that took a while to catch, as fonts were crashing our game at runtime.

And thanks heaps, that’d really be helpful for all developers if that was changed to ignore that setting or at least force it for all texture assets, especially for all the built in technologies and assets Unity provides that we’re unable to fix. There are some things like that that can genuinely save an enormous amount of time faced collectively by developers through little fixes like this. We’ve definitely lost a good number of days to direct and indirect problems relating to the read/write requirement.

OK, so we found the offending asset (it worked in 0.6.3) and unfortunately it’s not something that can be fixed with that suggested OnPreprocessTexture change.

Here’s what happened:

  • If a built-in texture is loaded into the runtime, it crashes, but we are unable to mark it readable, since it’s built-in.
  • Because it’s built-in, it doesn’t have a clear, regular file reference, and it doesn’t go through the normal asset import path.

We found that we had to grep all .mat, .prefab, .unity, .asset, .scene files for the following reference:

This is the fileID, guid pair for Default-ParticleSystem. We found it by creating a fresh project that referenced this built-in asset, copying its fileID/guid and searching our source files for a reference to it.

m_Texture: {fileID: 10307, guid: 0000000000000000f000000000000000, type: 0}

The problem remains, that any project that uses a built-in texture, that texture becomes a ‘poison-pill’ for your runtime, and the only fix is to not use a built-in texture. If possible, I think it would be great if the runtime didn’t crash when it saw a texture not marked readable, and just treated it as read/write, given that it’s a unfied memory platform (of course I may be being naive about engine details that mean this isn’t possible), but short of that, a full sweep would be needed for all built-in textures and systems that generate textures, like TextMeshPro (as an example).

If it’s at all possible, it’d be amazing if the runtime could start reporting the context for these errors too; in a perfect world the log would log the asset that references it as well as the texture itself. The symptom at run time is you get a log appear once per frame every frame and the game doesn’t progress. It errors out on a null pointer.

Importantly, please note, for some reason it seems as though this is only an issue when it comes from an asset bundle, but we’re not 100% certain just yet. A bug has been reported by tomas_unity812 and he has created a post about it:

Thanks for taking the time to follow this thread.

-Jack.

You can fix this by creating a readable copy of the texture, and assigning that instead of the one you had. It’s possible at runtime, but the operation feels incredibly dumb - blit the texture to a RenderTexture, then copy that RenderTexture into a new Texture that’s readable. Here’s the code from our code base, it’s pretty short. I haven’t used it in a while, so I have no idea what the render pipeline compatibility is. I’ve also never profiled it, as I never needed it at scale, so it might be bad. It might also be doing too much work? Idk.

public static class TextureExtensions {
    public static Texture2D GetReadableCopy(this Texture texture) {
        return GetReadableCopy(texture, texture.width, texture.height, texture.filterMode);
    }

    public static Texture2D GetReadableCopy(this Texture texture, FilterMode filterMode) {
        return GetReadableCopy(texture, texture.width, texture.height, filterMode);
    }

    public static Texture2D GetReadableCopy(this Texture texture, int copyWidth, int copyHeight, FilterMode filterMode) {
        // Create a temporary RenderTexture of the same size as the texture
        RenderTexture tmp = RenderTexture.GetTemporary(
            copyWidth,
            copyHeight,
            0,
            RenderTextureFormat.Default,
            RenderTextureReadWrite.Default);

        // Blit the pixels on texture to the RenderTexture
        Graphics.Blit(texture, tmp);
        // Backup the currently set RenderTexture
        RenderTexture previous = RenderTexture.active;
        // Set the current RenderTexture to the temporary one we created
        RenderTexture.active = tmp;
        // Create a new readable Texture2D to copy the pixels to it
        Texture2D myTexture2D = new Texture2D(copyWidth, copyHeight) {
            filterMode = filterMode
        };
        // Copy the pixels from the RenderTexture to the new Texture
        myTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
        myTexture2D.Apply();
        // Reset the active RenderTexture
        RenderTexture.active = previous;
        // Release the temporary RenderTexture
        RenderTexture.ReleaseTemporary(tmp);

        // "myTexture2D" now has the same pixels from "texture" and it's readable.
        return myTexture2D;
    }
}

@kapolka, this is a problem that props up often. I understand why things work like this - read/write enabled means that there’s two copies of the texture in memory, so that’s bad. But sometimes you really need the texture to be readable, and sometimes the texture is some annoying builtin resource that you can’t touch.
It would be very nice if it was possible to set the read/write enabled flag at runtime, with all the performance implications that would have.

Alternatively, a builtin function to copy a non-readable texture into a readable one so we wouldn’t have to maintain our own copy that needs to deal with Unity changing how blitting works every three hours.