EditableMesh 将应用的视觉网格更改为连接到 MeshPart 时,允许在 Studio 和体验中查询和修改网格。
一个 EditableMesh 可以从现有的 Content 的 MeshPart 或网格 ID 使用 AssetService:CreateEditableMeshAsync() 或空白 EditableMesh 创建,或使用 AssetService:CreateEditableMesh() 可以创建一个空白 。然后可以显示、修改和更新其碰撞模型。不是所有步骤都是必要的;例如,你可能想创建一个 EditableMesh 仅用于射线投射,而不显示它。
当它链接到新的 EditableMesh 时,将显示一个 MeshPart ,通过 AssetService:CreateMeshPartAsync() 。您可以创建更多 引用相同 的实例,或通过 链接到现有的 。
要重新计算编辑后的碰撞和流体几何图形,您可以再次调用 AssetService:CreateMeshPartAsync() 和 MeshPart:ApplyMesh() 来更新现有的 MeshPart 。一般建议在概念编辑结束后执行此操作,而不是在调用个别方法来操作几何图形之后。网格的视觉变化始终会立即反映在引擎上,无需调用 AssetService:CreateMeshPartAsync() 。
启用可编辑的网格对已发布的体验
为了安全目的,默认情况下,使用 EditableMesh 对发布的体验失败。要启用使用,EditableMesh,你必须年满 13 岁并身份验证通过。验证通过后,打开 Studio 的 游戏设置,选择 安全 ,启用 允许网格和图像 API 切换。请记住,在启用切换之前,查看使用条款。
权限
为了防止滥用,AssetService:CreateEditableMeshAsync() 只允许您加载和编辑网格资产:
- 这些是由体验的创建者拥有的(如果体验由个人拥有)。
- 这些是由群组拥有的(如果体验由群组拥有)。
- 这些是由登录的 Studio 用户拥有的(如果地点文件尚未保存或发布到 Roblox)。
如果使用 API 来加载不满足上述条件的资产,它们将抛出错误。
固定尺寸网格
当从现有网格资产中创建一个 EditableMesh 时(通过 AssetService:CreateEditableMeshAsync() ),结果的可编辑网格默认为固定尺寸。固定尺寸的网格在内存方面更高效,但您无法更改边顶点、面或属性的数量。只能编辑顶点属性和位置的值。
稳定的垂直/面 ID
许多 EditableMesh 方法使用 vertex , normal , UV , color 和 face ID。这些在 Luau 中被视为整数,但需要一些特殊处理。主要区别是,ID 是稳定的,即使其他部分的网格发生变化,它们也是相同的。例如,如果一个 EditableMesh 有五个边顶 {1, 2, 3, 4, 5} ,如果你移除边顶 4 ,那么新的边顶将是 {1, 2, 3, 5} 。
请注意,ID 不保证是按顺序排列的,因此,当遍历垂直或面时,您应该遍历由 GetVertices() 或 GetFaces() 返回的表。
分割垂直面属性
一个 边角 是面的角落,并且可以将面连接在一起。顶点可以有几个属性:位置、正常、UV坐标、颜色和透明度。
有时对于所有接触顶点的面都有用使用相同的属性值,但有时你会想让不同的面使用不同的属性值在同一顶点上。例如,在光滑的球体上,每个边点只有一个正常。相反,在立方体的角落,顶点将有 3 个不同的正常(每个邻近面都有一个)。您还可以在 UV 坐标或顶点颜色上有缝隙或锋利的变化。
当创建面时,每个vertex默认会拥有每个属性中的一个:一个正常值、一个UV坐标和一个颜色/透明度。如果你想创建缝合,你应该创建新属性并将它们设置在面上。例如,这段代码会创建一个锋利的立方体:
local AssetService = game:GetService("AssetService")
-- 给出 4 个顶点 ID,添加新的正常和 2 个三角形,制作锋利的四角
local function addSharpQuad(eMesh, vid0, vid1, vid2, vid3)
local nid = eMesh:AddNormal() -- 这会创建一个正常 ID,它会自动计算
local fid1 = eMesh:AddTriangle(vid0, vid1, vid2)
eMesh:SetFaceNormals(fid1, {nid, nid, nid})
local fid2 = eMesh:AddTriangle(vid0, vid2, vid3)
eMesh:SetFaceNormals(fid2, {nid, nid, nid})
end
-- 使6边之间的边缘增加的立方体
local function makeSharpCube()
local eMesh = AssetService:CreateEditableMesh()
local v1 = eMesh:AddVertex(Vector3.new(0, 0, 0))
local v2 = eMesh:AddVertex(Vector3.new(1, 0, 0))
local v3 = eMesh:AddVertex(Vector3.new(0, 1, 0))
local v4 = eMesh:AddVertex(Vector3.new(1, 1, 0))
local v5 = eMesh:AddVertex(Vector3.new(0, 0, 1))
local v6 = eMesh:AddVertex(Vector3.new(1, 0, 1))
local v7 = eMesh:AddVertex(Vector3.new(0, 1, 1))
local v8 = eMesh:AddVertex(Vector3.new(1, 1, 1))
addSharpQuad(eMesh, v5, v6, v8, v7) -- 前
addSharpQuad(eMesh, v1, v3, v4, v2) -- 返回
addSharpQuad(eMesh, v1, v5, v7, v3) -- 左
addSharpQuad(eMesh, v2, v4, v8, v6) -- 右侧
addSharpQuad(eMesh, v1, v2, v6, v5) -- 底部
addSharpQuad(eMesh, v3, v7, v8, v4) -- 顶部
eMesh:RemoveUnused()
return eMesh
end
卷线
网格面有前面和后面。当绘制网格时,默认情况下只绘制面的前部,尽管您可以通过设置网格的 DoubleSided 属性为 true 来更改此情况。
面周围的边缘点的顺序决定你是否正在查看前部或后返回。当垂直向前时,面的前部可见,当垂直向后时,面的后部可见。

限制
EditableMesh 目前有 60,000 个边和 20,000 个三角形的限制。尝试添加太多边或三角形会导致错误。
概要
方法
添加新颜色到几何图形,并返回稳定的颜色 ID。
添加新的正常到几何图形,并返回稳定的正常 ID。
添加新的三角形到网格并返回稳定的面 ID。
添加新的 UV 到几何体并返回稳定的 UV ID。
添加新的vertex到几何图形中,并返回稳定的vertex ID。
摧毁网格。
找到网格表面上最接近的点。
找到最接近特定点的坐标点的vertex。
查找特定球体内的所有边点。
返回与给定面相邻的面列表。
返回与给定边点相邻的边点列表。
返回给定颜色ID的颜色。
返回指定颜色 ID 的颜色 alpha(透明度)。
返回网格的所有颜色。
返回面的颜色 ID,用于面上的边顶点。
返回面的正常 ID,用于面上的边顶点。
返回面的 UV ID,用于面上的边顶点。
返回面的顶点 ID。
返回网格的所有面。
返回给定普通ID的普通向量。
返回网格的所有正常。
获取vertex的位置。
返回指定的 UV ID 的 UV 坐标。
返回网格的所有 UV。
返回所有顶点为一列稳定顶点 ID 列表。
返回描述稳定ID的字符串,有助于调试目的。
合并触碰在一起的边点。
使用稳定的面 ID 去除一个面。
移除所有未使用的边顶点、正常、UV和颜色,并返回移除的ID。
将此普通 ID 重置为自动计算。
设置颜色为颜色 ID。
设置颜色 alpha(透明度)为颜色 ID。
将面的顶点颜色设置为新的颜色 ID。
将面的顶点正常设置为新的正常 ID。
将面的顶点 UV 设置为新的 UV ID。
将面的顶点设置为新的顶点 ID。
设置正常ID的正常值。
在网格的本地对象空间中设置一个vertex位置。
设置 UV 坐标为 UV ID。
将网格上的所有面分为三角形
属性
方法
AddColor
添加新颜色到几何图形,并返回稳定的颜色 ID。
参数
返回
新颜色的稳定颜色 ID。
AddNormal
添加新的正常值到几何图形,并返回稳定的正常 ID。如果未指定正常值,正常将自动计算。
参数
普通矢量力。如果未指定普通值,普通将自动计算。
返回
新常态的稳定普通 ID。
AddTriangle
添加新的三角形到网格并返回稳定的面 ID。
参数
三角形的第一个顶点的 ID。
三角形第二个顶点的 ID。
三角形的第三个顶点的 ID。
返回
新脸部的稳定面 ID。
AddVertex
添加新的vertex到几何图形中,并返回稳定的vertex ID。
参数
在网格的本地对象空间中的位置。
返回
新边缘的稳定vertex ID。
Destroy
摧毁网格内容,立即回收使用的内存。
返回
FindClosestPointOnSurface
找到网格表面上最接近的点。返回面部ID,指向本地对象空间的网格,以及面部内部位置的坐标。见 RaycastLocal() 获取更多关于椭圆坐标的信息。
参数
网格的本地对象空间中的点位置。
返回
面 ID tuple、在本地对象空间上的网格点以及脸部内的位置坐标。
FindClosestVertex
找到空间中最接近特定点的vertex并返回稳定的vertex ID。
参数
网格的本地对象空间中的点位置。
返回
最接近稳定顶点 ID 到指定空间点。
FindVerticesWithinSphere
查找特定球体内的所有边点并返回一列稳定边点ID列表。
参数
返回
请求球体内稳定边界ID列表。
GetAdjacentVertices
给出稳定的顶点 ID,返回邻近顶点列表。

参数
绕着哪个垂直 ID 获得邻近垂直。
返回
给定垂直ID周围的邻近边缘的ID列表。
GetColorAlpha
返回指定稳定颜色 ID 的颜色 alpha(透明度)。
参数
获取Alpha的颜色ID。
返回
颜色 alpha 在请求稳定颜色 ID。
GetFaceUVs
返回面的 UV ID,用于面上的边顶点。
参数
用于获取 UV ID 的面部识别。
返回
用于指定面上的顶点的 UV ID 列表。
GetPosition
获取网格本地对象空间中vertex的位置。
参数
稳定的垂直 ID,用于获取位置。
返回
在网格本地对象空间中的顶点位置。
IdDebugString
返回描述稳定ID的字符串,用于调试目的,如 f17 或 v12 ,包含类输入、ID号和版本。
参数
用于返回调试信息字符串的ID。
返回
描述ID以人阅读可读格式的字符串。
MergeVertices
合并触碰在一起的边点,使用单个边点 ID,但保留其他原始属性 ID。
参数
在那里,边顶被认为相互接触的距离。
返回
将旧的vertex ID映射到新的vertex ID以融合已合并的垂直,
RaycastLocal
投射射线并返回交叉点、面 ID 和球心坐标。该方法的输入和输出位于网格的本地对象空间。
一个 椭圆坐标 是指将面内的一个点指定为面的 3 个边缘的权重组合的方式。这有助于作为一般方法来融合vertex特性。看这个方法的代码示例作为说明。
参数
返回
交叉点、面 ID 和楔形坐标的 tuple。
代码示例
This code finds the position and UV coordinates of the closest point on an EditableMesh to the input point.
local AssetService = game:GetService("AssetService")
-- Initialize EditableMesh in space
local editableMesh = nil
local success, errorMsg = pcall(function()
editableMesh = AssetService:CreateEditableMeshAsync(Content.fromUri("rbxassetid://ASSET_ID"))
end)
local meshPart = nil
if success and editableMesh then
meshPart = AssetService:CreateMeshPartAsync(
Content.fromObject(editableMesh),
{ CollisionFidelity = Enum.CollisionFidelity.Hull }
)
meshPart.Parent = workspace
else
print(errorMsg)
end
local function castRayFromCamera(position)
if not meshPart then
return
end
-- Create ray from camera along the direction of a clicked point
local camera = workspace.CurrentCamera
local ray = camera:ScreenPointToRay(position.X, position.Y)
-- Convert to object space to use with RaycastLocal()
local relativeOrigin = meshPart.CFrame:PointToObjectSpace(ray.Origin)
local relativeDirection = meshPart.CFrame:VectorToObjectSpace(ray.Direction)
local triangleId, point, barycentricCoordinate
triangleId, point, barycentricCoordinate = editableMesh:RaycastLocal(relativeOrigin, relativeDirection * 100)
if not triangleId then
-- Didn't hit any triangles
return
end
-- Interpolate UVs within the triangle
local vert1, vert2, vert3 = editableMesh:GetTriangleVertices(triangleId)
local uv0 = editableMesh:GetUV(vert1)
local uv1 = editableMesh:GetUV(vert2)
local uv2 = editableMesh:GetUV(vert3)
local u = (barycentricCoordinate.x * uv0.x) + (barycentricCoordinate.y * uv1.x) + (barycentricCoordinate.z * uv2.x)
local v = (barycentricCoordinate.x * uv0.y) + (barycentricCoordinate.y * uv1.y) + (barycentricCoordinate.z * uv2.y)
return Vector2.new(u, v)
end
SetColorAlpha
设置颜色 alpha(透明度)为颜色 ID。
参数
返回
SetFaceColors
将面的顶点颜色设置为新的颜色 ID。
参数
返回
SetFaceNormals
将面的顶点正常设置为新的正常 ID。
参数
返回
SetFaceUVs
将面的顶点 UV 设置为新的 UV ID。
参数
返回
SetFaceVertices
将面的顶点设置为新的顶点 ID。
参数
返回
SetNormal
设置一个正常ID的正常值。这将更改每个使用正常ID的面向的顶点的正常值。
参数
返回
SetPosition
在网格的本地对象空间中设置一个vertex位置。
参数
返回
Triangulate
将网格上的所有面分为三角形目前,由于只能创建三角形,因此无需做任何操作,但如果您的代码依赖于三角形,建议您在调用 AssetService:CreateEditableMeshAsync() 之后调用此方法。