Unity 中的 Mesh 和 Renderer 详解:从模型数据到画面显示

前言

在 Unity 开发中,经常会听到两个词:MeshRenderer

简单理解:

  • Mesh 负责描述物体的几何数据,比如顶点、三角形、UV、法线。
  • Renderer 负责把这些数据交给渲染管线,结合材质、光照、相机等信息,最终显示到屏幕上。

如果把一个 3D 物体比作一件商品:

  • Mesh 是商品的形状结构。
  • Material 是商品的外观材质。
  • Renderer 是把商品摆到镜头前并让它能被看见的展示系统。

一、Mesh 是什么?

Mesh 是 Unity 中表示网格模型的数据结构。一个常见的 3D 模型,本质上就是由大量三角形拼接而成的表面,而这些三角形又由顶点组成。

Mesh 本身不负责显示,它只保存模型的几何信息。

1. Mesh 中常见的数据

一个 Mesh 通常包含以下几类核心数据:

数据 作用
Vertices 顶点坐标,决定模型的基本形状
Triangles 三角形索引,决定顶点如何组成面
Normals 法线,影响光照计算
UV 贴图坐标,决定纹理如何贴到模型表面
Tangents 切线,常用于法线贴图
Colors 顶点颜色,可用于特殊表现
Bounds 包围盒,用于视锥裁剪等优化

2. 顶点和三角形

在 Unity 中,一个最简单的 Mesh 可以只包含顶点和三角形索引。

例如,一个三角形需要 3 个顶点:

csharp 复制代码
Vector3[] vertices =
{
    new Vector3(0, 0, 0),
    new Vector3(1, 0, 0),
    new Vector3(0, 1, 0)
};

int[] triangles =
{
    0, 1, 2
};

这里的 triangles 数组并不是直接存坐标,而是存顶点数组的索引。0, 1, 2 表示使用第 0、1、2 个顶点组成一个三角形。

3. 三角形顶点顺序

Unity 默认通过三角形顶点顺序判断正反面。通常情况下,面朝摄像机的一侧才会被渲染,背面会被剔除,这叫做背面剔除。

如果模型看不见,但数据又没有报错,常见原因之一就是三角形索引顺序反了。


二、MeshFilter 是什么?

Mesh 是数据,但它不能直接挂到 GameObject 上。Unity 通常使用 MeshFilter 组件来保存静态网格引用。

常见组合是:

  • MeshFilter:保存 Mesh。
  • MeshRenderer:负责渲染 Mesh。

一个普通 3D 模型对象通常长这样:

text 复制代码
GameObject
├── Transform
├── MeshFilter
└── MeshRenderer

其中:

  • MeshFilter.sharedMesh 指向模型网格资源。
  • MeshRenderer.sharedMaterial 指向材质资源。

MeshFilter 只负责"这个物体用哪个网格",它本身不决定显示效果。


三、Renderer 是什么?

Renderer 是 Unity 中所有渲染组件的基类。它负责让物体进入渲染流程。

常见的 Renderer 类型包括:

Renderer 类型 用途
MeshRenderer 渲染普通静态 Mesh
SkinnedMeshRenderer 渲染带骨骼动画的 Mesh
SpriteRenderer 渲染 2D Sprite
LineRenderer 渲染线段
TrailRenderer 渲染拖尾
ParticleSystemRenderer 渲染粒子

对于 3D 模型来说,最常见的是 MeshRendererSkinnedMeshRenderer

1. MeshRenderer

MeshRenderer 通常和 MeshFilter 搭配使用。

它主要负责:

  • 引用材质。
  • 参与光照计算。
  • 设置阴影投射和接收。
  • 设置渲染层级、Probe、Motion Vector 等渲染参数。
  • 将 MeshFilter 中的 Mesh 提交给渲染管线。

注意:MeshRenderer 自己不保存 Mesh 数据,它需要从同一个 GameObject 上的 MeshFilter 获取 Mesh。

2. SkinnedMeshRenderer

SkinnedMeshRenderer 用于角色、怪物、可变形模型等带骨骼动画的对象。

它和 MeshRenderer 的区别是:

  • MeshRenderer 渲染静态网格。
  • SkinnedMeshRenderer 会根据骨骼动画实时改变顶点位置。

角色模型通常不需要 MeshFilter,因为 SkinnedMeshRenderer 自身就持有 Mesh 和骨骼信息。


四、Mesh、Material、Renderer 的关系

很多初学者会把 Mesh、Material、Renderer 混在一起。可以这样区分:

概念 负责内容 是否决定形状 是否决定外观 是否负责显示
Mesh 几何数据
Material 材质和 Shader 参数
Renderer 渲染组件 部分参与

一个物体能显示出来,通常需要三个条件:

  1. 有 Mesh 数据。
  2. 有 Renderer 组件。
  3. 有可用的 Material。

缺少其中任意一项,都可能导致物体无法正常显示。


五、手动创建一个 Mesh

下面通过代码创建一个最简单的三角形 Mesh。

csharp 复制代码
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class SimpleTriangleMesh : MonoBehaviour
{
    private void Start()
    {
        Mesh mesh = new Mesh();
        mesh.name = "Simple Triangle";

        Vector3[] vertices =
        {
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(0, 1, 0)
        };

        int[] triangles =
        {
            0, 1, 2
        };

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        MeshFilter meshFilter = GetComponent<MeshFilter>();
        meshFilter.mesh = mesh;
    }
}

使用方式:

  1. 创建一个空物体。
  2. 挂载上面的脚本。
  3. 给物体的 MeshRenderer 设置一个材质。
  4. 运行场景即可看到一个三角形。

这里的关键点是:

  • Mesh 创建几何数据。
  • MeshFilter 接收 Mesh。
  • MeshRenderer 使用材质把它渲染出来。

六、mesh 和 sharedMesh 的区别

Unity 中经常会看到两个属性:

csharp 复制代码
meshFilter.mesh
meshFilter.sharedMesh

它们的区别非常重要。

1. mesh

访问 meshFilter.mesh 时,Unity 可能会自动复制一份 Mesh 实例。适合运行时修改当前对象自己的网格。

例如:

csharp 复制代码
Mesh mesh = meshFilter.mesh;
mesh.vertices = newVertices;
mesh.RecalculateNormals();

这种方式修改的是当前对象使用的 Mesh 实例,通常不会影响其他使用同一个资源的对象。

2. sharedMesh

sharedMesh 指向共享的 Mesh 资源。多个对象可能引用同一个 sharedMesh

如果直接修改 sharedMesh,可能会影响所有引用这个 Mesh 的对象,甚至影响项目资源。

因此:

  • 运行时想单独修改某个物体,优先使用 mesh
  • 编辑器工具或明确要修改共享资源时,才使用 sharedMesh

七、material 和 sharedMaterial 的区别

Renderer 上也有类似概念:

csharp 复制代码
renderer.material
renderer.sharedMaterial

1. material

访问 renderer.material 时,Unity 会为当前 Renderer 创建材质实例。适合运行时单独修改某个物体的颜色、透明度等参数。

csharp 复制代码
Renderer renderer = GetComponent<Renderer>();
renderer.material.color = Color.red;

2. sharedMaterial

sharedMaterial 指向共享材质资源。修改它会影响所有使用该材质的对象。

如果只是想改变一个物体的颜色,不建议直接修改 sharedMaterial


八、渲染流程简化理解

一个 Mesh 最终显示到屏幕,大致会经历以下过程:

  1. GameObject 提供 Transform 信息。
  2. MeshFilter 提供 Mesh 几何数据。
  3. MeshRenderer 提供 Material 和渲染设置。
  4. Camera 判断物体是否在视野内。
  5. Unity 根据渲染管线、Shader、光照、阴影等信息绘制物体。
  6. 最终结果输出到屏幕。

可以简化为:

text 复制代码
Mesh 数据
    ↓
MeshFilter 持有网格
    ↓
MeshRenderer 结合材质和渲染设置
    ↓
Camera + Render Pipeline
    ↓
屏幕显示

九、常见问题

1. 为什么 Mesh 创建了却看不到?

常见原因:

  • 没有 MeshRenderer
  • 没有设置材质。
  • 三角形索引顺序反了。
  • Mesh 的顶点坐标太小、太远或不在摄像机视野内。
  • 没有调用 RecalculateBounds(),导致包围盒异常。
  • 材质使用的 Shader 不兼容当前渲染管线。

2. 为什么修改一个模型,其他模型也变了?

通常是因为修改了共享资源:

  • 修改了 sharedMesh
  • 修改了 sharedMaterial

如果只想修改当前对象,应该使用:

csharp 复制代码
meshFilter.mesh
renderer.material

3. 为什么模型有些面显示,有些面不显示?

可能是以下原因:

  • 三角形顶点顺序不一致。
  • 法线方向错误。
  • 材质开启了背面剔除。
  • 模型导入时法线或面方向存在问题。

4. MeshRenderer 和 SkinnedMeshRenderer 怎么选?

简单判断:

  • 静态模型、场景物体、道具:使用 MeshRenderer
  • 角色、带骨骼动画的模型、需要蒙皮变形的模型:使用 SkinnedMeshRenderer

十、性能注意点

1. 控制 Mesh 顶点数和三角形数量

顶点和三角形越多,渲染成本越高。移动端项目尤其需要控制模型复杂度。

2. 避免频繁修改 Mesh

如果每帧修改 Mesh 顶点,需要注意 CPU 开销和内存分配。可以尽量复用数组,减少临时对象创建。

3. 合理使用静态合批和动态合批

对于大量不动的物体,可以考虑 Static Batching。对于小型动态物体,可以关注 Dynamic Batching 或 GPU Instancing。

4. 注意材质数量

Renderer 的材质数量会影响 Draw Call。相同 Mesh 如果使用不同材质,通常不能直接合并为同一次绘制。

5. 使用 LOD

远处模型可以使用低模,减少渲染压力。Unity 提供了 LODGroup 组件用于管理不同距离下的模型精度。


总结

Unity 中的 MeshRenderer 是两个不同层面的概念:

  • Mesh 是模型的几何数据,决定物体长什么形状。
  • Renderer 是渲染组件,决定物体是否以及如何被绘制。
  • MeshFilter 是普通静态 Mesh 和 MeshRenderer 之间的桥梁。
  • Material 和 Shader 决定物体表面的视觉效果。

理解它们之间的关系后,再去学习模型导入、程序化建模、Shader、渲染管线、性能优化等内容,会清晰很多。

一句话概括:

Mesh 负责"形状",Material 负责"外观",Renderer 负责"显示"。

相关推荐
丁小未2 小时前
Unity动态图集方案
unity·游戏引擎
元气少女小圆丶5 小时前
停止单机,开始学一点后台通信吧
unity
丁小未6 小时前
Unity高效的DOTS动画方案Rukhanka深度剖析
unity·游戏引擎·rukhanka·dots动画·gpu动画·gpuecsanimation
玖玥拾1 天前
Unity 3D 基础(一)Unity基础架构、物理系统、视觉渲染、空间变换与对象查询
笔记·游戏·3d·unity·游戏引擎
玖玥拾3 天前
C# 语言进阶(十四)Unity UI界面开发 + 网络消息联动
服务器·开发语言·网络·ui·unity·c#·游戏引擎
野区捕龙为宠3 天前
Unity 持久化数据
unity·游戏引擎·lucene
郝学胜-神的一滴3 天前
[简化版 GAMES 101] 计算机图形学 17:纹理技术从基础原理到多场景实战应用
c++·unity·游戏引擎·图形渲染·three.js·opengl·unreal