文章目录
一、前言
虽然 Unity
支持许多常见的图像格式作为导入纹理的源文件(例如 JPG、PNG、PSD 和 TGA
),但在3D
图形硬件(如显卡或移动设备)的实时渲染过程中不会使用这些格式。3D
图形硬件要求纹理以专门格式进行压缩,这些格式针对快速纹理采样进行了优化。各种不同的平台和设备都有自己不同的专有格式。
默认情况下,Unity Editor
会自动将纹理转换为最合适的格式,以匹配我们选择的构建目标(如Android、iOS
)。只有转换后的纹理才会包含在我们的构建中;源资源文件保留为原始格式,位于项目的Assets
文件夹中。
我们可以对纹理选择不同的压缩格式(例如,如果使用纹理作为遮罩,只有一个通道,则可以选择使用 BC4
格式来节省空间,同时保持质量)。
二、图片导入到Unity中尺寸会变成2的N次方
如果你将一张图片导入到Unity
中,你会发现默认被转成了2的N次方
大小。
比如下面这张图原图尺寸是640x1138
导入到Unity
中,看到尺寸变成了512x1024
这是因为图片的纹理像素在Unity
中需要遵循2的N次方
,由图形学决定。
我们也可以设置不转换,设置Non-Power of 2
为None
,此时图片就会保持原尺寸了。
不过不推荐这样做,因为最终图片加载到显存中,也会进行转换为2的N次方
,而这个转换比较耗时,所以可能会导致卡顿。
三、为什么非要是2的N次方呢
那么,为什么非要是2的N次方
呢?
打个不是很恰当的比方,现在我们建了一所小学,每间教室最多安排32
个座位。
现在学校招生,如果招的学生数量不是32
的整数倍,那么就会浪费教室。比如招了33
个学生,那么多出来的1
个学生只能安排到另外的一间教室,导致老师上完课还得再跑另外这间教室单独给这个学生再上一次课,这也对资源和时间的一种浪费。
如果学生数量是32
的整数倍,那就不会浪费资源和时间了。
四、常用的压缩格式
纹理压缩格式 | 描述 | 大小(256×256 像素纹理) | 平台支持 |
---|---|---|---|
RGBA 32 位 | 真实色彩,有 Alpha。这是具有 Alpha 通道的纹理的最高质量压缩格式。 | 256KB(32 位/像素) | 所有平台。 |
RGBA 16 位 | 低质量真实色彩。这是具有 Alpha 通道的纹理的默认压缩格式。 | 128KB(16 位/像素) | 所有平台。 |
Alpha 8 | 高质量 Alpha 通道,但没有任何颜色。 | 64KB(8 位/像素) | 所有平台。 |
RGB 16 位 | 65,000 种颜色,没有 Alpha。使用比压缩格式更多的内存,但可能更适合没有渐变的 UI 或清晰纹理。 | 128KB(16 位/像素) | 所有平台。 |
RGBA Compressed PVRTC 4 位 | 压缩 RGB 纹理。高质量纹理,尤其是颜色数据,但可能需要很长时间压缩。 | 32KB(4 位/像素) | Android (PowerVR)、iOS、tvOS。 |
RGB Compressed PVRTC 4 位 | 压缩 RGB 纹理。高质量纹理,尤其是颜色数据,但可能需要很长时间压缩。 | 32KB(4 位/像素) | Android (PowerVR)、iOS、tvOS。 |
RGBA Compressed PVRTC 2 位 | 高压缩 RGBA 纹理。质量低,但较小,因此提高了性能。 | 16KB(2 位/像素) | Android (PowerVR)、iOS、tvOS。 |
RGB Compressed PVRTC 2 位 | 高压缩 RGB 纹理。质量低,但较小,因此提高了性能。 | 16KB(2 位/像素) | Android (PowerVR)、iOS、tvOS。 |
RGB Compressed ETC | 压缩 RGB 纹理。这是适用于 Android 项目的不带 Alpha 通道的纹理的默认纹理压缩格式。 | 32KB(4 位/像素) | Android、iOS、tvOS。注意:ETC1 受到所有 OpenGL ES 2.0 GPU 的支持。它不支持 Alpha。 |
RGB Compressed ETC2 | 压缩 RGB 纹理。 | 32KB(4 位/像素) | Android (OpenGL ES 3.0) 。注意:在不支持 ETC2 的 Android 平台上,纹理在运行时解压缩为 Build Settings 中的 ETC2 fallback 指定的格式。 |
五、监听资源导入事件,自动化处理压缩格式
我们有时候需要在导入资源的时候做一些自动化处理,比如导入图片自动设置压缩格式等,此时我们就需要使用AssetPostprocessor
这个类了。
示例代码如下:代码放入Editor
文件夹下
using UnityEngine;
using System.Collections;
using UnityEditor;
public class MyEditor : AssetPostprocessor {
//模型导入之前调用
public void OnPreprocessModel()
{
Debug.Log ("OnPreprocessModel="+this.assetPath);
}
//模型导入之前调用
public void OnPostprocessModel(GameObject go)
{
Debug.Log ("OnPostprocessModel="+go.name);
}
//纹理导入之前调用,针对导入的纹理进行设置
public void OnPreprocessTexture()
{
Debug.Log ("OnPreProcessTexture="+this.assetPath);
TextureImporter impor = this.assetImporter as TextureImporter;
impor.textureFormat = TextureImporterFormat.ARGB32;
impor.maxTextureSize = 512;
impor.textureType = TextureImporterType.Advanced;
impor.mipmapEnabled = false;
}
public void OnPostprocessTexture(Texture2D tex)
{
Debug.Log ("OnPostProcessTexture="+this.assetPath);
}
public void OnPostprocessAudio(AudioClip clip)
{
}
public void OnPreprocessAudio()
{
AudioImporter audio = this.assetImporter as AudioImporter;
audio.format = AudioImporterFormat.Compressed;
}
//所有的资源的导入,删除,移动,都会调用此方法,注意,这个方法是static的
public static void OnPostprocessAllAssets(string[]importedAsset,string[] deletedAssets,string[] movedAssets,string[]movedFromAssetPaths)
{
Debug.Log ("OnPostprocessAllAssets");
foreach (string str in importedAsset) {
Debug.Log("importedAsset = "+str);
}
foreach (string str in deletedAssets) {
Debug.Log("deletedAssets = "+str);
}
foreach (string str in movedAssets) {
Debug.Log("movedAssets = "+str);
}
foreach (string str in movedFromAssetPaths) {
Debug.Log("movedFromAssetPaths = "+str);
}
}
}