> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/3d-jian-mo-yu-dong-hua/meshes.md).

# 网格

了解导入到 Decentraland 的 3D 模型支持哪些网格属性。

3D 模型有一个 *网格* ，由三角形 *面*组成。这些面彼此在 *边* 上相接（它们接触的线），并在 *顶点* 上相接（它们角点相连的位置）。

{% hint style="info" %}
**💡 提示**：安装 [Decentraland Tools Blender 插件](https://extensions.blender.org/add-ons/decentraland-tools/)。它包含一些实用功能，可帮助你编辑和导出 3D 模型、可穿戴物品和表情动作。
{% endhint %}

## 空间限制

你场景中的所有 3D 模型都必须位于其地块范围内。如果在预览运行时，模型的任何部分超出这些范围，超出的部分将被裁掉且不会渲染。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c9f4c9448f2fb3c7a2d85a4dd16f31814b0878bf%2Fcut-train.png?alt=media\&token=af46a450-fbd9-481f-9a28-87b7cc78925f)

在 Creator Hub 编辑器中，你会看到模型被标红，其包围盒也会以红色标出。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-a44ea3779c9fc579f367e0cbefb2b4218369eab9%2Ftrain-out-of-bounds.png?alt=media\&token=b9cc5fff-1980-4980-8cc3-626784d656fd)

{% hint style="info" %}
**📔 注意**：在较早的 Decentraland Web 客户端中，出于性能原因，如果 3D 模型的任何部分超出边界，即使只是包围盒超出，整个模型也不会被渲染。到了 Decentraland 2.0 桌面客户端，只有模型中超出边界的部分会被裁掉。模型中位于场景内的部分会被渲染。
{% endhint %}

## 边界框

如果你的模型的所有顶点都整齐地位于场景区域内，但它的包围盒很大且大部分为空，并延伸到了场景限制之外，那么在 Creator Hub 中整个模型都会被标记为超出场景限制。位于你地块内的模型部分会正常渲染，而且你仍然可以发布你的场景。

每个网格都有一个包围盒，用于包裹形状的边界。为了让 3D 模型在 Decentraland 中更易用，请确保其包围盒不要比模型本身必要地延伸得更远。

为避免这个问题，你可以清理你的 3D 模型，重置网格的位置和旋转，使包围盒不要超出它们所包裹的网格。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-3188e3d33635429246de0f2d7f8f810483135233%2F07-apply-rotations.gif?alt=media\&token=9de03c16-3b43-4483-a974-4787f251d38f)

*在 Blender 中，你可以通过选中对象，按 Ctrl+A，然后应用“全部变换”来做到这一点。*

例如，当旋转模型边缘附近的子网格时要小心。由于包围盒是立方体，即使网格是圆形的，在旋转 45° 后，其包围盒的角也可能会伸出来。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-38697f7d74f05eee44d500f06cb076936d1c0eac%2F10-apply-rotation.png?alt=media\&token=95db55ad-6d4e-4a0c-a7f4-ff9a94a133f3)

我们建议你烘焙模型中每个网格的旋转和缩放，以确保不会有不必要的包围盒超出其应有尺寸。

## 三角形限制

由于 Decentraland 是一个充满不同场景和对象的开放世界，而这些内容会在同一 3D 空间中按需下载，因此优化我们的网格非常重要，以便在游玩时获得良好性能。从这个意义上说，关于网格，我们始终需要牢记一些场景限制：

> n 代表场景占用的地块数量。

* **三角形：** n x 10000 场景中所有模型的三角形总数。
* **高度：** 330 米，不受地块数量影响。
* **文件大小：** 每个地块 15 MB - 最大 300 MB 上传到内容服务器的文件总大小。包括 3D 模型和音频。不包括未上传的文件，例如 node.js 包。
* **每个文件最大 50 MB** 场景中的任何单个文件都不能超过 50 MB，无论该场景有多少地块。

更多信息请查看所有场景限制 [这里。](https://docs.decentraland.org/creator/development-guide/scene-limitations/)

{% hint style="warning" %}
**🔥优化提示🔥：添加多边形数量** 一个很有价值的提示是始终跟踪模型的 polycount。要在 Blender 中做到这一点，你需要在视口覆盖层面板中开启统计信息。

<img src="https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-b1595d1e8b5529e0d12e99de25246215f1bdc900%2F41-stats.gif?alt=media" alt="" data-size="original">
{% endhint %}

## 大型场景中的网格

在创建网格时，我们应该牢记以下 2 个最佳实践：

* **模块化：** 将大型网格拆分为更小、模块化的部分。例如，不要把整个建筑做成一个单独的网格，而是可以将建筑拆分为各个墙面、地板和建筑不同区域的独立网格。这样可以让 Unity 的视锥裁剪更有效地工作，因为只有可见部分需要参与渲染计算。它还会改善内存占用，因为同一个网格可以在不同位置被重复用于同一个对象多次（要做到这一点，你需要在 SDK7 场景定义中引用同一个网格，或者在从 Blender 导出场景时使用实例而不是复制对象）。
* **包围体**：确保每个对象的包围体尽可能紧密贴合。包围体中多余的空间会导致对象在不可见时也被渲染。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-dce0bc9b716ee8b44c7b8daf0d7b9b4e76bdeaa7%2F40-modularity.png?alt=media\&token=9b4d8e51-ab22-481b-9a3e-9f686f15bfc1)

### 什么是视锥裁剪？

视锥裁剪是一种优化技术，它会禁用位于摄像机视野范围之外的对象的渲染器（网格）。请看这两个示例：

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-1330fc3816764d5c82d75f6381929f0321bf0412%2F18-frustum-culling.png?alt=media\&token=cb7c171f-db28-4478-ba15-0c041bcf84d9)

*一个类似迷宫的室内关卡。这个普通的场景视图显示了所有可见的游戏对象。*

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c33a68dba5eb29a0f36573d3dd2c4e8b73addd0f%2F19-frustum-culling-2.gif?alt=media\&token=59b22e24-14af-4a3e-86a1-18817a19196d)

*常规视锥裁剪只会渲染摄像机视野内的对象。这是自动发生且始终如此。*

## 对象实例化 vs 对象复制

在 Blender 中，复制一个对象会创建该对象的完全独立副本，而实例化一个对象会创建一个与原始对象共享相同数据的副本。

当一个对象被复制时，它会创建一个带有完全独立数据集的新对象，包括其所有几何体、材质和动画。这意味着对原始对象所做的任何更改都不会反映到复制对象上，反之亦然。

另一方面，当一个对象被实例化时，对原始对象所做的任何更改都会反映到它的所有实例上，反之亦然。因为所有实例共享相同的底层数据。

从性能角度看，实例化通常比复制高效得多，尤其是在处理复杂场景或大量对象时更是如此。这是因为实例化比复制占用更少内存，因为它不会为每个实例创建新数据。此外，实例化还能让 Blender 将所有实例视为单个对象来优化渲染流程，而不是分别渲染每个复制对象。

总的来说，实例化可以成为提升 Blender 以及你的 Decentraland 场景中的性能和工作流效率的强大工具，尤其是在处理大型复杂场景时。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-cc521f833d170857bee4aa12fec1d9f645c46446%2F20-duplicate-objects.png?alt=media\&token=f10a541b-7ba1-47ba-b2dc-c3cfcf0f8e79)

在某些情况下，当复制树木、植物和路灯这类对象时，与直接复制相比，实例化可以显著提升性能。例如，这个场景有十四根路灯杆，它们完全相同。我们知道每根路灯有两种不同的纹理，一种用于灯杆，另一种用于灯光。所以在这种情况下，我们会有两次绘制调用，每种纹理一次。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-717d26a8b05990d9e19f7b3becaac8122de944a3%2F21-duplicate-objects-2.png?alt=media\&token=1b277f98-7fbc-46d7-ae3f-c6779907b4cd)

在 Blender 中，当你处于在空间中克隆并摆放元素的阶段时，你有三种选择：复制、实例化或合并对象。

让我们分析一下每种流程的优缺点。

### 复制对象

| 菜单：  | 对象 ‣ 复制对象 |
| ---- | --------- |
| 快捷键： | Shift-D   |

这将创建所选对象在视觉上完全相同的副本，但它们会被视为不同的对象。因此，在导出时，每个对象都会有 2 次绘制调用，2 \* 14 = 28 次绘制调用，总磁盘占用为 320kb。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-36c86406e9de1a3c1029ab6a77bcbced976f77b7%2F22-duplicate-objects-3.png?alt=media\&token=fea4df0e-8338-499c-9b74-6ec379b0f941)

### 实例化对象

| 面板：  | 工具栏 ‣ 工具 ‣ 编辑 ‣ 复制链接 |
| ---- | -------------------- |
| 菜单：  | 对象 ‣ 复制链接            |
| 快捷键： | Alt-D                |

这将创建一个新对象，其所有数据都链接到原始对象。如果你在编辑模式中修改某个链接对象，所有链接副本都会被修改。变换属性仍然是副本而不是链接，所以你仍然可以自由旋转、缩放和移动，而不会影响其他副本。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-e20a046d7790b5e3f03dce96a9d14e050257cfb5%2F23-instancing.png?alt=media\&token=f7f36a81-55ad-498f-9e91-b9431f80c773)

*当我们导出这些模型时，绘制调用次数仍然相同（28 次）。不过请注意，现在我们只有一个网格，这会显著减少磁盘占用（41 kb）。*

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-99e3bbd682033748343d03febe334f602aba3bcb%2F24-instancing-2.png?alt=media\&token=feb60e01-7e54-4f85-bac1-beae639a5295)

*为了保持组织有序，你可以简单地在场景中实例化集合，这样就能从一个文件夹和一个源头控制所有实例。*

{% hint style="info" %}
**💡 提示**：同样的逻辑也适用于 SDK 端。十四个实体都指向同一个 `GltfContainer` 文件时，其行为就像实例一样：文件只下载一次，只转换一次，而且无论有多少实体使用它，其网格和纹理只会在内存中保留一份。把同样的内容拆分成十四个几乎相同的 *.glb* 文件则相当于复制，会给你带来十四次下载和内存中的十四份副本。 *.glb* 文件则相当于复制，会给你带来十四次下载和内存中的十四份副本。
{% endhint %}

### 合并对象

| 菜单：  | 对象 ‣ 合并 |
| ---- | ------- |
| 快捷键： | Ctrl-J  |

这会把所选对象合并为一个只有单一网格的对象。它在对象模式下工作，会把所有内容合并到最后一个被选中的 *active* 对象，并且要求所有选中的对象类型相同。材质会被保留并合并，因此我们那十四根路灯杆不再是十四个可渲染对象，而变成一个，引擎会用 2 次绘制调用而不是 28 次来绘制它们——每种材质一次，只绘制一次。

这是三种选项中唯一真正减少绘制调用的方法，重要的是要明确原因：Decentraland 引擎会在运行时根据流式内容构建你的场景，因此它无法像对预先烘焙好的内容那样，为你分组或批处理重复对象。如果你需要更少的绘制调用，必须在 Blender 中完成合并。

这种减少并非没有代价。合并会一次放弃几项东西：

* **磁盘占用会再次上升。** 合并后的网格会存储全部十四根杆子的几何体，因此你失去了实例化带来的节省。
* **视锥裁剪变成非此即彼。** 只要合并对象的任何部分出现在屏幕上，它就会被完整绘制。沿街分布的十四根路灯杆几乎总会有一根可见，所以你最终会一直把全部十四根都绘制出来——这很容易比你节省下来的绘制调用代价更高。
* **各部分不再能被单独访问。** 你将无法再移动、播放动画、点击或隐藏单独一根路灯杆，因为最后只剩下一个对象了。

应谨慎使用合并：适用于许多小型道具，它们总是一起出现在同一位置，且从不交互，并且只有在你确认对象数量确实正在拖累性能之后才使用。对其他情况，实例化通常是更好的默认选择。

{% hint style="warning" %}
**📔 注意**：将十四个独立对象导出到一个单独的 *.glb* 文件中， **不是** 就是合并。引擎仍然会看到十四个对象，并且仍然会发出 28 次绘制调用。只有将网格合并在一起才会改变这个数量。
{% endhint %}

## 网格命名

为你的网格使用有意义的名称。名称应当提供资产使用位置或其所对应对象部位的上下文。

为资产命名时，使用以下组合： `PascalCase` 和 `snake_case`，我们可以称之为 `PascalSnake_case`。基本规则如下——新单词或分隔符（`_`）后面的单词以 **大写字母开头。**

* 为你的网格使用有意义的名称 **示例：** 🟢 **优先** 名称 - `剧院`, `电车` 🔴 **避免** 名称 - `Untitiled.008`, `primitive(1)`, `Cylinder.091`, `_sphere-AB`
* 使用下划线 `_` 作为分隔符，为名称添加更多上下文。把更常见的内容放在前面，把具体信息放在末尾。 **示例：** 🟢 **优先** 名称 - `喷泉雕像`, `剧院主墙`, `电车左轮` 🔴 **避免** 名称 - `北_主墙_剧院`, `电车_左前_轮`

如果有多个对象具有相同的名称，请在单词后加上数字： `喷泉雕像01、喷泉雕像02 等。`

## 创建模型的工具

有许多插件和外部工具可以帮助制作资源时的工作，让流程更快、更高效，其中有些是免费的，有些则需要购买，举例如下：

### 减面

这是一个众所周知的修改器，可用于在保持模型表面结构的同时减少网格的三角面数量。虽然它是优化模型的强大工具，但要注意，一旦对模型进行减面，拓扑结构可能会受到影响，造成不良拓扑（因为它会把几何体打碎成不可预测的碎片）。另一方面，减面会把网格的四边形转换为三角形，使其在使用后更难修改。就这一点而言 **减面适用于静态模型，但不适合动画模型。**

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-fa7269059815d6b0687b7b6c29ec632463318861%2F42-decimate-01.png?alt=media\&token=18606f4e-ddca-442e-9e29-b9af8fbef561) ![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-8ae651d7fd4bd8a23c60469f60cc8a572c2ad714%2F43-decimate-02.png?alt=media\&token=1ba84648-dff1-4cce-b2ad-85325ba7db2a)

另一种使用减面来优化网格的方法，是先对模型进行减面，然后再进行适当的重拓扑。这样可以确保结果更可预测，并获得干净的拓扑。

一些可能有用的重拓扑插件有（其中一些是付费的）：

* **Simplygon：** <https://www.simplygon.com/>
* **Speedretopo：** <https://blendermarket.com/products/speedretopo?ref=2>
* **Retopoflow：** <https://blendermarket.com/products/retopoflow>

### 镜像修改器

Blender 中的镜像修改器是一种通过将物体一半镜像到任意方向（X、Y、Z）来创建对称模型的工具。当你有对称模型时，这是一个很棒的工具，因为它可以减少 3D 建模和 UV 展开的时间（因为你只需要展开模型的一部分，剩余部分会共享相同的 UV 坐标），还可以通过避免在本质上是镜像的部分上浪费纹理分辨率来优化你的纹理。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c6259ae5fe095f0e4a22d7af8f8a84f7adfc98c1%2F44-mirror-modifier.png?alt=media\&token=8aaabb9b-c158-440e-b61a-1777e411d509)

### 批量重命名

一种非常方便、轻松更改命名规范的工具，是使用 Blender 集成在其工具集中的批量重命名。要访问它，请前往 *编辑* 然后 *批量重命名*.

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c02ecaff9c6765f3b0dcf164a506c4b39d015e9a%2F45-batch-rename.png?alt=media\&token=64658f91-f1af-462b-8bcb-340bd8026870)

选择你想要更改名称的对象，只需将默认对象名替换为新名称即可。此工具提供不同的方法和资产类型来重命名，因此它非常灵活，也可用于网格、动画、骨骼等名称的更改。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-6a91a4b355df03a163ec1cb3570753eedd05fc8f%2F47-batch-rename-methods.png?alt=media\&token=841e0544-8ae3-432d-aabe-2ac2be84cd0c) ![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-a6c301bd731a96d8813c4120ee554490e480f874%2F46-batch-rename-types.png?alt=media\&token=1f18300b-8a5b-47b5-915a-c4f9fa14057c)

## 几何体最佳实践 [#](https://docs.decentraland.org/creator/3d-modeling/meshes/#best-practices-for-geometries)

* 请留意你添加到 3D 模型中的面数，因为更多面会让渲染更费资源。请参见 [**场景限制**](https://docs.decentraland.org/creator/development-guide/scene-limitations/) 了解场景施加的限制。
* 确保没有看不见但会增加三角形数量的隐藏面。
* 对于应当具有圆润侧面的形状，请将其设为 *平滑* ，而不是添加额外的面。
* 确保所有面的 *法线* 都朝外而不是朝里。如果你模型中的某些面在渲染时似乎不见了，这很可能就是原因。
* 烘焙网格的旋转和缩放，以免其包围盒不必要地向外延伸。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-zh/3d-jian-mo-yu-dong-hua/meshes.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
