We are currently developing a 2D game in Unity for both Android and iOS.
After going through all the trouble of manually converting every image into a POT, allowing for PVRTC compression in iOS. Our current problem is to ensure that the graphics quality is good and similar in both platforms.
So far the best solution we found was to use mip maps in Android and not use them in iOS. This has two major disadvantages which is the need to two different configurations for each image, as the Mip maps option is not overridable for a specific platform; and that they both look different, but better than using one configuration in both.
Below we attached images that show the differences with and without mip maps in both platforms.
Thank you in advance.


The solution we found was to create our own shader, which included “tex2Dbias”.
We modified the sprites-default shader to add this option.
In case someone else needs it, here’s the complete shader, based on the article by bluescrn from http://inverseblue.com/?p=287:
Shader "Sprites/Modified"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_MainTexBias ("Mip Bias (-1 to 1)", float) = -0.65
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ PIXELSNAP_ON
#pragma shader_feature ETC1_EXTERNAL_ALPHA
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
fixed4 _Color;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif
return OUT;
}
sampler2D _MainTex;
sampler2D _AlphaTex;
half _MainTexBias;
fixed4 SampleSpriteTexture (float2 uv)
{
fixed4 color = tex2D (_MainTex, uv);
#if ETC1_EXTERNAL_ALPHA
// get the color from an external texture (usecase: Alpha support for ETC1 on android)
color.a = tex2D (_AlphaTex, uv).r;
#endif //ETC1_EXTERNAL_ALPHA
return color;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2Dbias(_MainTex, half4(IN.texcoord.x, IN.texcoord.y, 0.0, _MainTexBias)) * IN.color;
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
The texture importer doesn’t have a platform specific option for mip-maps, but this can still be achieved. There’s a property called mipMapBias, that controls when mip-maps are used depending on the distance from the camera. Lesser bias will instruct the texture to use mip-maps at further distances.
public float mipMapBiasForIos = -1000f;
void Awake () {
if (Application.platform == RuntimePlatform.IPhonePlayer) //iOS
{
GetComponent<Renderer>().material.mainTexture.mipMapBias = mipMapBiasForIos;
}
}