Unity3D编辑器之修改贴图片默认导入规则

贴图导入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.
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了。

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.yxkfw.com/thread-69943-1-1.html

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值