I've been trying to fix this for several days now and I'm not really sure how. First I'm creating AssetBundles which have prefabs and GameObjects with Textures. After building the AssetBundle, it's uploaded to a server, and in another Android app, I retrieve it and unload its assets. Everything works fine on the Unity editor "Game View", but on the android phone, the textures of dynamic GameObjects appear black. Static textures, like the texture I'm using for the background, appear normally on both the editor and the android device. The textures which appear black are those that I retrieve from the AssetBundles.
When I searched about it, I came across these suggestions:
- It might have to do with compression. The problem is, these textures are retrieved from AssetBundles on the server dynamically. I can not "build" the project with the suggested settings after I unload them from the bundle. I tried automatically compressing the images to "Compressed ETC 4 Bits" before loading them in the AssetBundle, and it didn't solve the issue. https://forum.unity.com/threads/black-textures-on-some-devices-android-versions.195328/
- I also tried to do it manually by loading the texture (and material) from the AssetBundle and assigning it to the loaded object, but it still only appears in the Editor, not the phone. https://answers.unity.com/questions/238109/problem-with-materials-after-creating-asset-bundle.html
- I tried saving the image as a sprite before loading it to the AssetBundle. And in the app I tried creating a new texture with that sprite, but that approach also didn't work. https://answers.unity.com/questions/651984/convert-sprite-image-to-texture.html
First I drag and drop the image for the texture and it gets automatically compressed using this function:
// Automatically Compress all imported textures to the project to ETC_RGBA
void OnPreprocessTexture(Texture2D t)
{
EditorUtility.CompressTexture(t, TextureFormat.ETC_RGBA8_3DS, TextureCompressionQuality.Normal);
}
Then I manually add the texture to a 3D GameObject in the editor and create a prefab and add that GameObject to it. I add the prefab itself, the material and the image to the AssetBundle and do this to export the AssetBundle: (Now the AssetBundle contains 3 assets in total. I upload it to a server)
//Creates a new menu (Build Asset Bundles) and item (Normal) in the Editor
[MenuItem("Assets/Build Asset Bundles/Normal")]
static void BuildABsNone()
{
BuildPipeline.BuildAssetBundles("Assets/AssetBundle", BuildAssetBundleOptions.None, BuildTarget.Android);
}
In the app, I dynamically load the AssetBundle from a server and I want to show it on top of an ImageTarget using Vuforia. This is part of the IEnumerator DownloadAndCache() function in the CloudHandler class which loads the material asset and instantiates the GameObject "mBundleInstance". I then display that "mBundleInstance" on an image target:
bundle = www.assetBundle;
var materials = bundle.LoadAllAssets(typeof(Material));
containsMaterial = (materials.Length > 0);
if (AssetName == "")
{
mBundleInstance = Instantiate(getMainAsset(bundle)) as GameObject;
}
else
{
mBundleInstance = Instantiate(bundle.LoadAsset(AssetName, typeof(GameObject))) as GameObject;
}
Debug.Log(mBundleInstance.GetComponent<Renderer>().material.mainTexture.name);
//returns the correct name of the compressed png image
if (containsMaterial)
{
foreach (Material m in materials)
{
var shaderName = "Standard";
var newShader = Shader.Find(shaderName);
if (newShader != null)
{
m.shader = newShader;
mBundleInstance.GetComponent<Renderer>().material = m;
Debug.Log("actual texture name: " + mBundleInstance.GetComponent<Renderer>().material.mainTexture.name);
//returns the correct name of the png image
}
else
{
Debug.LogWarning("unable to refresh shader: " + shaderName + " in material " + m.name);
}
}
}
Here is how it looks like in the Editor's GameView: Texture of GameObject appears: (The King of Diamonds image)
And this is how it looks like on the Android device: Texture of Gameobject does not appear.
Since there's no visible error, I'm not really sure why this bug happens. Any help or suggestion why this happens or what I can do to fix it?