贴图导入unity后会自动设置成压缩格式,它会先判断贴图是否有透明通道。
Android:不带透明通道压缩成ETC1,带透明通道压缩成ETC2,不被4整除fall back到RGBA32
IOS: 不带透明通道压缩成RGB PVRTC,带透明通道压缩成RGBA PVRTC ,不是2的整数次幂fall back到RGBA32
Texture图片拖入的时候,如下图所示,unity会默认设置ToNerest,这样会自动保证Android平台下图片被4整除,IOS平台下图片是2的整除次幂,所以默认情况下图片都可以得到最好的压缩。
但是如果是在做UGUI的话,由于需要将Texture设置成Sprite那么它就不会ToNearest了,这样就会导致一个问题。美术同学很难保证图片的尺寸是2的整数次幂,这样IOS下就都无法进行压缩了。
通过上面的问题我想做一件事就是当UI图片拖入unity的时候,自动设置图片的最优格式。(最优解只用于大图模式,也就是长宽一遍超过128另一边超过64这样的图,这样的图不适合放在图集中)
1.美术同学虽然很难保证图片是2的整数次幂,但是保证图片能被4整除这一点很容易,所以我会要求她们提供的图片必须被4整除。
2.Android下优先设置图片规则才用ETC+Crunched的格式,如果图片无法被4整除在设置ASTC格式,如果安卓手机不支持ASTC则会fall back到RGBA32
3.IOS下优先设置图片规则采用PVRTC4,如果图片不是2的整数次幂在设置ASTC格式,如果不支持fall back到RGBA32
4.我们只提供图片首次导入最优方案,后面是可以在修改的。比如一张被4整除并且带ALPHA的图片,根据这个规则导入后会自动设置ETC2+Crunched格式,但是如果美术同学觉得效果不好,后面可以在修改成ASTC RGBA 4X4 或者RGBA32.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
using System.IO; using System.Reflection; using UnityEditor; using UnityEngine; public class ImportPicture : AssetPostprocessor { void OnPreprocessTexture() { TextureImporter importer = assetImporter as TextureImporter; if (importer != null) { if (IsFirstImport(importer)) { importer.textureType = TextureImporterType.Sprite; TextureImporterPlatformSettings settings = importer.GetPlatformTextureSettings("iPhone"); bool isPowerOfTwo = IsPowerOfTwo(importer); TextureImporterFormat defaultAlpha = isPowerOfTwo ? TextureImporterFormat.PVRTC_RGBA4 : TextureImporterFormat.ASTC_RGBA_4x4; TextureImporterFormat defaultNotAlpha = isPowerOfTwo ? TextureImporterFormat.PVRTC_RGB4 : TextureImporterFormat.ASTC_RGB_6x6; settings.overridden = true; settings.format = importer.DoesSourceTextureHaveAlpha() ? defaultAlpha : defaultNotAlpha; importer.SetPlatformTextureSettings(settings); settings = importer.GetPlatformTextureSettings("Android"); settings.overridden = true; settings.allowsAlphaSplitting = false; bool divisible4 = IsDivisibleOf4(importer); defaultAlpha = divisible4 ? TextureImporterFormat.ETC2_RGBA8Crunched : TextureImporterFormat.ASTC_RGBA_4x4; defaultNotAlpha = divisible4 ? TextureImporterFormat.ETC_RGB4Crunched : TextureImporterFormat.ASTC_RGB_6x6; settings.format = importer.DoesSourceTextureHaveAlpha() ? defaultAlpha : defaultNotAlpha; importer.SetPlatformTextureSettings(settings); } } } //被4整除 bool IsDivisibleOf4(TextureImporter importer) { (int width, int height) = GetTextureImporterSize(importer); return (width % 4 == 0 && height % 4 == 0); } //2的整数次幂 bool IsPowerOfTwo(TextureImporter importer) { (int width, int height) = GetTextureImporterSize(importer); return (width == height) && (width > 0) && ((width & (width - 1)) == 0); } //贴图不存在、meta文件不存在、图片尺寸发生修改需要重新导入 bool IsFirstImport(TextureImporter importer) { (int width, int height) = GetTextureImporterSize(importer); Texture tex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); bool hasMeta = File.Exists(AssetDatabase.GetAssetPathFromTextMetaFilePath(assetPath)); return tex == null || !hasMeta || (tex.width != width && tex.height != height); } //获取导入图片的宽高 (int, int) GetTextureImporterSize(TextureImporter importer) { if (importer != null) { object[] args = new object[2]; MethodInfo mi = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance); mi.Invoke(importer, args); return ((int)args[0], (int)args[1]); } return (0, 0); } } |
这里会先判断DoesSourceTextureHaveAlpha图片是否带透明通道,选择对应的最优解、这里还有个问题是就是一般我们需要将UI的大图放在指定的目录下,也就是上面的代码应该只处理指定目录下的图片。可以判断路径,但是这样会产生另一个问题就是美术先把图片放入unity中,然后在将图片移动在刚刚指定的UI目录下,如果是这样的操作上述代码中的OnPreprocessTexture就不会执行了。所以我们需要监听资源导入成功事件,如果是移动到UI目录下的话就重新ImportAsset了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static bool forceImport = false; static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { foreach (string str in movedAssets) { if (str.Contains("UI保存路径")) { forceImport = true; //重新reimport并且强制 IsFirstImport AssetDatabase.ImportAsset(str); // 如果是移动到指定UI目录下,需要重新Import } } } |
- 本文固定链接: https://www.xuanyusong.com/archives/4663
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
一个图集里有多种压缩格式,会生成多个图集,比如有3种或者4种压缩格式,会生成3到4个图集,就会有3到4个DrawCall吧
请问哪里可以知道 GetWidthAndHeight 可以通过反射获得?头疼哦
试了下,如果不SaveAndReimport,根本没生效额?保存了打包才有改变
MoMo大佬,我有个问题,就是Git拉取下来的新贴图,IsFirstImport 会返回true,貌似是tex是空,meta存在,所以返回true,这样可能就会覆盖其他同事专门处理的贴图,请问怎么处理这种情况~
已经解决了,每次加入新贴图后,将userdata设置为一个固定string,然后在脚本里多加一层userdata的判断就可以避免上面我说的这种情况~
你好,请问怎么设置userdata
请问下,对于精灵选择压缩格式,最后自动打成图集会有影响吗?手动建立的图集压缩设置会覆盖掉这里更改的设置吧?
MoMo大佬,可不可以讲讲unity的可寻址资源系统。3Q~
可以,其实我们自己模拟了一套类似的可寻址资源系统