Unity基础:材质与纹理入门——给物体穿上“衣服“

Unity基础:材质与纹理入门——给物体穿上“衣服“
Unity基础材质与纹理入门——给物体穿上衣服大家好欢迎回到Unity教程系列。上一篇文章我们学会了如何创建和操作基本的3D物体但你可能会觉得——那些白花花或纯色的方块看起来太无聊了。今天这篇文章我们要让游戏物体变得赏心悦目起来。材质和纹理是游戏视觉表现的基石。它们决定了场景中的每个物体的外观——墙壁是木头还是砖石角色是穿着布衣还是铠甲地面是草地还是沙漠。理解了材质与纹理的工作原理你就能给游戏世界穿上衣服让它变得生动而丰富。一、材质与纹理的基本概念1.1 什么是材质Material 材质Material是定义物体表面外观的数据集合。它告诉渲染引擎这个物体表面应该是什么颜色、有多少反光、是粗糙还是光滑、是否透明、是否发光等等。一个材质本质上是一个Shader着色器 一组参数值的组合。Shader决定了怎么算颜色材质的参数决定了具体算什么颜色。类比理解如果把Shader比作一道菜的配方决定怎么做材质就是按照这个配方做出来的具体一道菜放了多少盐、多少辣椒。1.2 什么是纹理Texture 纹理Texture是一张二维图片它被包裹在3D模型的表面提供精细的视觉细节。纹理是材质最重要的参数之一——没有纹理物体就是纯色的有了纹理物体可以有木纹、砖纹、布料纹理等丰富的细节。常见的纹理类型Albedo / Base Map基色贴图定义物体表面的基本颜色和图案。这是最常用的纹理比如一块木板的木纹、一面墙的砖纹。Normal Map法线贴图模拟表面凹凸细节而不增加模型面数。蓝色调的图片让低面数模型看起来有高面数模型的细节。Metallic Map金属度贴图指定表面的哪些部分是金属、哪些部分不是。白色区域是金属黑色区域不是。Smoothness / Roughness Map光滑度贴图指定表面的哪些区域更光滑、哪些更粗糙。Emission Map自发光贴图指定表面的哪些区域会自发光如机器人的眼睛、能量核心等。Height Map高度贴图提供表面的高度信息用于视差映射等高级效果。Ambient Occlusion Map环境光遮蔽贴图模拟角落和缝隙中的环境光阴影。1.3 材质、纹理和Shader的关系这三者之间的关系可以用一句话概括Shader是渲染算法材质是算法的参数集纹理是参数的一种图片类型的参数。Shader (Standard) ────定义了基于物理的渲染PBR的计算方法 │ └── Material (Mat_Wood) ────使用Standard Shader并设置了具体的参数 ├── Albedo: wood_texture.png木材贴图作为基色 ├── Normal Map: wood_normal.png木材的法线贴图 ├── Metallic: 0木材不是金属 ├── Smoothness: 0.3木材比较粗糙 └── Tiling: (1, 1)二、创建和应用材质2.1 在Unity中创建材质① 在Project窗口中进入你想要存放材质的文件夹如果没有Materials文件夹先创建一个。② 右键 → Create → Material。③ 新材质出现在Project窗口中命名为M_FirstMaterial建议材质以M_前缀命名方便搜索和管理。④ 选中材质在Inspector中看到材质的属性面板。2.2 材质属性面板详解以Unity内置的Standard Shader为例Built-in渲染管线材质面板的主要属性Rendering Mode渲染模式Opaque不透明默认模式用于完全不透明的物体墙壁、石头、木箱等。这是性能最好的模式。Cutout镂空用于有完全透明区域的物体树叶、栅栏的铁丝网配合Alpha Cutoff阈值使用。要么完全透明要么完全不透明。Fade渐隐物体整体可以半透明适合淡入淡出效果。但有一些光照计算上的限制。Transparent透明用于玻璃、水等需要真实透明度的物体支持不同区域的不同透明度。Albedo基色/反照率颜色选择器设置物体的基本颜色纹理槽拖拽贴图到这里作为基色纹理颜色与纹理的关系纹理的每个像素颜色会乘以这里设置的颜色。如果颜色设为白色纹理以原始颜色显示如果颜色设为红色纹理整体偏红。Metallic金属度0为完全非金属电介质1为完全金属。真实世界中的物体要么是金属要么不是很少有中间值所以通常设为0或1。光滑的非金属如光滑塑料和光滑的金属如不锈钢看起来完全不同——金属会反射出有色高光。Smoothness光滑度0为完全粗糙漫反射1为完全光滑镜面反射。金属和非金属都可以有不同的光滑度。Normal Map法线贴图给表面添加凹凸细节。法线贴图是一张蓝紫色的特殊贴图通过改变每个像素的法线方向来模拟凹凸不平的表面效果。Height Map高度贴图配合视差映射Parallax Mapping使用提供更强的深度感和立体感。Emission自发光让材质从内部发光。可以设置发光颜色、强度和发光贴图。用于制作灯光面板、屏幕、魔法符文、能量核心等发光物体。注意自发光材质在Baked GI中可以影响周围的静态物体。Tiling平铺和Offset偏移Tiling的X和Y值控制纹理在物体表面的重复次数。设为(2,2)意味着纹理在水平方向和垂直方向各重复2次图案变得更密集。Offset控制纹理的偏移量用于微调纹理在物体表面的位置。2.3 给物体应用材质有三种方式给GameObject应用材质方式一拖拽最常用将材质从Project窗口直接拖到Scene视图中的物体上。松手后物体立即改变外观。方式二从Inspector赋值① 选中物体② 在Inspector中找到MeshRenderer组件③ 在Materials数组中找到Element 0④ 将材质拖到槽位中或点击槽位右侧的圆形选择器搜索材质方式三拖到Hierarchy将材质从Project窗口拖到Hierarchy中的GameObject名称上。2.4 多个材质与子网格一个MeshRenderer可以包含多个材质槽对应模型的不同子网格SubMesh。例如一个角色模型可能分成了身体和武器两个子网格在Materials数组中分别使用不同的材质。在代码中操作材质// 获取并修改物体的第一个材质// 注意这会创建材质实例的副本MaterialmatGetComponentRenderer().material;mat.colorColor.red;// 获取共享材质不会创建实例副本推荐用于批量操作MaterialsharedMatGetComponentRenderer().sharedMaterial;// 获取所有材质Material[]materialsGetComponentRenderer().materials;materials[0].colorColor.blue;GetComponentRenderer().materialsmaterials;⚠️ 注意material和sharedMaterial的区别material返回该物体的材质实例副本。修改它只会影响这一个物体但会增加DrawCall。sharedMaterial返回共享的材质资源。修改它会影响所有使用该材质的物体但不会创建副本。如果在运行时修改了material属性Unity会自动创建该材质的副本称为Material Instance这会导致额外的内存占用和DrawCall。如果确实需要运行时修改大量物体的材质属性建议使用MaterialPropertyBlock。三、纹理的导入与设置3.1 获取纹理资源你可以从以下途径获取纹理Unity Asset Store搜索Free Textures有大量免费的纹理包可以直接下载导入。免费纹理网站Poly Havenpolyhaven.com提供高质量PBR纹理集AmbientCGambientcg.com免费PBR材质库OpenGameArtopengameart.org游戏开发纹理资源自己制作使用Photoshop、GIMP、Substance Designer等工具制作自定义纹理。3.2 导入纹理到Unity最简单的方式将图片文件PNG、JPG、TGA等直接从文件管理器拖拽到Unity的Project窗口中。导入后Unity会自动处理纹理并显示在Project窗口中。选中纹理在Inspector中可以看到纹理导入设置Texture Import SettingsTexture Type纹理类型这是最重要的设置决定了纹理的用途Default默认类型用于3D模型的纹理Normal Map法线贴图Unity会进行特殊处理Sprite (2D and UI)用于2D精灵和UI元素Lightmap光照贴图专用Editor GUI and Legacy GUI编辑器界面用Cursor自定义鼠标光标Cookie灯光Cookie纹理Single Channel单通道纹理Texture Shape纹理形状2D普通2D纹理最常用Cube立方体贴图天空盒、环境反射用sRGB (Color Texture)如果纹理是颜色信息如Albedo贴图勾选此选项。如果是数据纹理如法线贴图、金属度贴图需要取消勾选以确保数据精度不被颜色空间转换影响。Alpha SourceAlpha通道的来源。可以是从纹理文件本身读取或者从灰度图生成。Generate Mip Maps是否生成MipMap多级渐远纹理。MipMap可以优化远距离的纹理渲染质量并提升性能但会增加约33%的内存占用。对于3D场景中的纹理一般建议开启。Max Size纹理的最大尺寸限制。例如设为1024则导入的4K纹理会被缩小到1024×1024。这是控制纹理内存占用的重要设置——在移动平台上通常把非关键纹理控制在512或1024以下。Compression压缩格式。不同平台有不同的最佳压缩格式PCDXTRGB或BC7RGBA高质量iOSASTC最佳选择AndroidETC2通用兼容或ASTC较新设备3.3 纹理的过滤模式与包裹模式Filter Mode过滤模式Point (no filter)最近邻采样。像素风格明显适合像素风游戏。Bilinear双线性过滤。在4个相邻像素之间插值质量适中性能适中。Trilinear三线性过滤。在双线性基础上还在MipMap级别之间插值。质量最好但内存带宽开销最大。Aniso Level各向异性过滤级别提高倾斜角度观察纹理时的清晰度。对于地面纹理特别有用。值为0时不使用值越高效果越好但性能开销越大。**Wrap Mode包裹模式**控制纹理UV坐标超出0-1范围时的行为Repeat重复纹理在超出范围时重复平铺。适合地板、墙壁等需要连续纹理的场合。Clamp钳制纹理边缘像素被拉伸以填充超出区域。适合UI元素、独立图标等。Mirror镜像纹理以镜像方式重复。Mirror Once镜像一次后钳制。四、动手实践4.1 创建木箱材质① 创建一个新材质命名为M_WoodCrate。② 将Albedo颜色设为偏暖的棕色。③ 将Metallic设为0木材不是金属。④ 将Smoothness设为0.2-0.3木材比较粗糙。⑤ 如果有法线贴图拖到Normal Map槽中你会看到木材纹理出现了明显的凹凸感。⑥ 将材质拖到场景中的一个Cube上——现在它看起来像一个木箱了。4.2 做一面砖墙① 创建新材质命名为M_BrickWall。② Albedo颜色偏红棕色。③ 由于墙壁通常很大适当提高Tiling值。将Tiling的X和Y都设为(3,3)或更高让纹理图案更密集。④ Metallic设为0Smoothness设为0.1。⑤ 将材质应用到墙壁Cube上。4.3 创建一个金属球① 创建新材质命名为M_PolishedMetal。② 将Albedo颜色设为深灰色或暗金色。③ 将Metallic设为1完全金属。④ 将Smoothness设为0.7-0.9光滑金属。⑤ 将材质应用到球体上。观察——球体现在看起来像一个真正的金属球能反射周围环境通过天空盒Cubemap。4.4 制作发光物体① 创建新材质命名为M_GlowMagic。② Albedo设为白色或浅色。③ 勾选Emission选项。④ 将Emission的颜色设为亮色比如亮蓝色或亮橙色调节强度。⑤ 将材质应用到场景中的一个物体上。即使在暗处这个物体也会发出光芒。五、代码中动态操作材质5.1 修改材质属性usingUnityEngine;publicclassMaterialController:MonoBehaviour{privateRendererrend;voidStart(){rendGetComponentRenderer();}// 改变颜色publicvoidChangeColor(Colorcolor){rend.material.colorcolor;}// 修改金属度使用Shader属性名publicvoidSetMetallic(floatvalue){rend.material.SetFloat(_Metallic,Mathf.Clamp01(value));}// 修改光滑度publicvoidSetSmoothness(floatvalue){rend.material.SetFloat(_Glossiness,Mathf.Clamp01(value));}// 闪烁效果协程publicSystem.Collections.IEnumeratorFlicker(floatduration,floatinterval){floatelapsed0;ColororiginalColorrend.material.color;while(elapsedduration){rend.material.colororiginalColor*Random.Range(0.3f,1f);yieldreturnnewWaitForSeconds(interval);elapsedinterval;}rend.material.colororiginalColor;}}5.2 MaterialPropertyBlock——避免创建材质副本当需要在运行时修改材质属性时直接使用renderer.material会创建材质实例的副本增加内存占用和DrawCall。对于批量物体的属性修改更好的做法是使用MaterialPropertyBlockusingUnityEngine;publicclassEfficientMaterialChange:MonoBehaviour{privateRendererrend;privateMaterialPropertyBlockpropBlock;voidStart(){rendGetComponentRenderer();propBlocknewMaterialPropertyBlock();}publicvoidSetColorWithoutInstance(Colorcolor){// 使用MaterialPropertyBlock不会创建材质副本rend.GetPropertyBlock(propBlock);propBlock.SetColor(_Color,color);rend.SetPropertyBlock(propBlock);}}六、纹理导入常见问题6.1 纹理显示模糊降低Max Size可以减小纹理内存占用但设置过小会导致模糊。确保Max Size不小于纹理在屏幕上实际需要的分辨率。对于UI和近距离观察的纹理保持较高的Max Size。6.2 纹理重复太多或太少调整Tiling值。Tiling越大纹理在物体表面重复越多次。一般大面积的地面和墙壁需要较大的Tiling值2-5而小型道具通常用1即可。6.3 材质在Build后显示异常检查Shader是否被正确打包。在Graphics Settings中确保使用的Shader被包含在Always Included Shaders列表中或者在资源中有引用。七、本篇总结✅ 本文核心知识点回顾材质Material定义物体表面外观——颜色、金属度、光滑度、透明度等纹理Texture是二维图片为材质提供精细的视觉细节Albedo、Normal Map、Metallic、Smoothness是PBR材质的核心属性纹理导入设置中的Max Size和Compression直接影响运行时的内存占用renderer.material会创建材质实例副本批量修改应使用sharedMaterial或MaterialPropertyBlockTiling控制纹理的平铺密度Offset控制纹理的位置偏移 下一篇文章将学习Camera相机组件——透视投影与正交投影的区别以及如何通过控制相机来决定玩家看到什么。动手任务① 创建至少5个不同外观的材质木材、金属、石头、玻璃、发光② 尝试下载免费纹理贴图并导入到材质中使用③ 调整Tiling和Offset观察纹理变化④ 写一个简单脚本在运行时动态改变物体的颜色关于作者拥有多年Unity开发经验的游戏开发者专注Unity系统化教学与最佳实践分享。欢迎在评论区交流讨论