IOS下拆分Unity图集的透明通道(不用TP)

91 篇文章 3 订阅

转载 https://zhuanlan.zhihu.com/p/32674470

IOS下拆分Unity图集的透明通道(不用TP)

flashyiyi

flashyiyi

程序员,B站UP

 

这就是IOS目前PVRTC对透明图的压缩效果。

有人说是Unity没有用“正版”的PVRTC压缩库的原因,但是我专门去下载了独立版的PVRTexTool,对比图如下,你觉得哪个是独立版的效果呢?

都是垃圾,又何必要分出个高下。

 

Unity安卓下已经自带图集ETC1+Alpha了,ETC2的效果也都还不错,回过头,发现苹果系统才是目前的症结所在。其实苹果的透明图压缩质量一直都很差,只是为了满足安卓系统,透明图一般都会拆通道(或者干脆不压缩),不想对IOS单独处理就干脆全平台一起做了,使得IOS的问题并不明显。

然而现在安卓平台的问题都解决了,IOS的问题就显露了出来……虽然IOS也有了新格式ASTC,苦于普及率远不如ETC2(貌似是IP6以上才支持),想要遗弃掉PVRTC可能还得再等上一年。

所以,现阶段,我们只能选择单独对IOS平台拆分UI图集的透明通道,来解决UI压缩后完全不能看的问题。

 

工程文件:

flashyiyi/UGUIAlphaAtlas​

github.com图标

Editor/CreateAlphaAtlas.cs 创建透明通道图的编辑器脚本
Editor/CustomPackerPolicy.cs 自定义图集生成规则
AlphaAtlasManager.cs 透明通道图管理类
SplitImage.cs 可以显示透明通道的Image

 

0x1 生成Alpha图集:

首先需要切换到IOS平台,然后把图集里的图片格式设置为PVRTC RGBA(脚本现在只会影响这个格式的图集)

再执行Tools下的这个命令

便会在Resources/TextureAlphaAtlas目录下生成透明图集图片和配置文件

透明图是通过GL函数重新由未压缩的散图拼接而成的,相比直接从压缩过的图集中获取,质量会好很多

注意,执行这个命令之后,图集生成规则文件会自动更换为CustomPackerPolicy。它唯一的作用只是让原本是PVRTC RGBA的零散Sprite,在生成最终图集的自动转换成PVRTC RGB。

if (settings.format == TextureFormat.PVRTC_RGBA4 && forceIOSOpaque) //强制生成不透明图集
       settings.format = TextureFormat.PVRTC_RGB4;

必须保留这个配置文件,IOS下才是正确的。而在其他平台下,CustomPackerPolicy和默认的DefaultPackerPolicy并没有区别。但如果你曾经修改过图集规则,就需要注意下这个变化。

 

0x2 让透明图集生效:

方法1:

将之前生成的图集文件打入包内,再将所有的Image替换成专门的SplitImage.cs。这个SplitImage.cs重写了Image两个函数,会在运行期间加载透明图集。

public class SplitImage : Image
 {
        public override Material material
        {
            get
            {
                if (m_Material != null)
                    return m_Material;
                if (overrideSprite && (overrideSprite.associatedAlphaSplitTexture != null || AlphaAtlasManager.GetInstance().GetAlphaTexture(overrideSprite) != null))
                    return defaultETC1GraphicMaterial;
                return defaultMaterial;
            }
            set
            {
                base.material = value;
            }
        }
        protected override void UpdateMaterial()
        {
            base.UpdateMaterial();
            Texture2D alphaTex = AlphaAtlasManager.GetInstance().GetAlphaTexture(overrideSprite);
            if (alphaTex != null)
                canvasRenderer.SetAlphaTexture(alphaTex);
        }
}

结果:

未压缩 / 拆通道后 / 使用原始Image显示的情况

目前文件都是用Resources.Load直接加载的,可以修改AlphaAtlasManager里的加载逻辑以便引入AssetBoundles机制。

 

方法2(推荐)

PackAlphaAltas命令相当于一个打包AssetBoundles的预处理,它会在打包前手动修改Sprite的RD属性,将透明图挂在Sprite上。这样直接用原始的Image就能显示拆分通道后的Sprite了。

SerializedObject so = new SerializedObject(sprite);
so.FindProperty("m_RD.textureRect").rectValue = GetAltasTextureRect(sprite, atlasTexture);
so.FindProperty("m_RD.texture").objectReferenceValue = atlasTexture;
Texture2D alphaTexture = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/" + AlphaAtlasManager.TEXTURE_ALPHA_ATLAS_PATH + atlasTexture.name + "_alpha.png");
so.FindProperty("m_RD.alphaTexture").objectReferenceValue = alphaTexture;
so.ApplyModifiedProperties();

不过这会影响到项目原有的打包流程。可以把方法内的BuildPipeline.BuildAssetBundles部分替换成项目的打包方法,再调用PackAlphaAltas来打包,把两部分合并在一起。

EditorSettings.spritePackerMode = SpritePackerMode.Disabled;
BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundles", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.iOS);
EditorSettings.spritePackerMode = SpritePackerMode.AlwaysOn;

 

这个方案和安卓平台下的ETC1+Alpha表现是一致的,加载策略也相同。并不需要将图集文件手动打入包内,也不需要做额外的管理。AlphaAtlasManager.cs,SplitImage.cs这两个文件实际上可以删除。这样可以保证多平台逻辑的一致性。

 

0x3 延伸思考

虽然我们在这里使用的是Unity的自动图集,但在最后的打包过程里,实际上已经把自动图集功能关掉了,是靠手动修改数据文件,修改图片链接和textureRect来产生的图集效果。

所以,实际上这个做法也可以延用到TP上,修改赋值代码即可。

Unity自动图集最主要的优点,是可以一开始的时候不打图集,在最后才考虑图集的事情。也因为这个原因,修改图集归属是无成本的。

而这正是TP的缺点。

所以用同样的方法,在最后才接入TP的图集和结构数据,就能够综合两者的优点,扬长避短。

 

不过,TP比Unity图集多的功能也就是精灵的90度旋转了,紧密布局则是双方共有的(Unity2017的新版图集 & 自带图集实现TP的Polygon布局)。而且这些功能都需要修改UI组件才能获得支持,也并不必要。

本来就不使用TP的项目,倒也没必要引用一个大部分功能重复的三方库进来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity透明通道,是用来处理材质上的透明效果的。在渲染过程中,透明通道可以将物体的不透明部分和透明部分进行分离,并单独进行渲染。 透明通道通过透明度值来确定物体的不透明度,透明度取值范围为0到1之间,0表示完全透明,1表示完全不透明透明通道还可以用来实现一些特殊效果,比如半透明材质、水面透明效果等。 当我们使用透明通道时,需要注意一些问题。首先,需要在材质中开启透明通道,这样才能正确地渲染透明效果。其次,透明通道需要与其他渲染通道进行正确的排序,以确保透明物体的渲染顺序是正确的,否则可能导致渲染错误的结果。 在一些情况下,由于透明通道的处理原理,可能会出现“变点点”的现象。当多个透明物体重叠在一起时,透明效果可能会变得不稳定,表现为有些区域出现点点的不透明度,这是由于渲染顺序的问题导致的。 为了解决这个问题,我们可以通过调整透明物体的渲染顺序来避免这种现象。可以通过修改材质的渲染模式、调整物体的渲染顺序等方式来解决。此外,还可以使用一些优化技巧,如深度排序、透明物体裁剪等,来提升透明效果的质量。 总的来说,透明通道是实现透明效果的重要工具,但在使用过程中需要注意一些问题。只有正确处理透明物体的渲染顺序,才能确保透明效果的正确显示,避免出现“变点点”的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值