EditableMesh 將變更應用的視覺網格,當連接到 MeshPart 時,可以在 Studio 和體驗中查詢和修改網格。
啟用已發布的體驗
為了安全目的,使用 EditableMesh 對發布的體驗會預設失敗。要啟用使用,您必須年滿 13 歲且身份驗證通過。驗證通過後,開啟 Studio的遊戲設定,選擇 安全 ,並啟用 允許網格/圖像API 切換。
許可
為了防止濫用,AssetService:CreateEditableMeshAsync()只允許您載入和編輯網格資產:
- 這些是屬於體驗創作者的(如果體驗屬於個人)。
- 屬於群組所有的(如果體驗屬於群組)。
- 屬於登入的工作室用戶所擁有(如果位置檔案尚未儲存或發布到 Roblox)。
記憶限制
可編輯的資產目前對記憶使用成本高昂。為了減少對客戶端性能的影響,EditableMesh 有嚴格的客戶端記憶預算,雖然伺服器、Studio 和插件都使用無限記憶。使用 FixedSize 可能會幫助您保持在記憶預算內,在某些情況下,將一個 EditableMesh 連接到多個 MeshParts (多重參考) 可能會幫助記憶優化。
創建和顯示
一個 EditableMesh 可以從現有的 Content 的 MeshPart 或網格ID使用 AssetService:CreateEditableMeshAsync() 或空白 EditableMesh 來創建,或使用 AssetService:CreateEditableMesh() 來創建空白 。然後可以顯示、修改和更新其碰撞模型。不是所有步驟都是必要的;例如,你可能想創建一個 EditableMesh 只是為了射線而不顯示它。
local AssetService = game:GetService("AssetService")
-- 創建空白可編輯網格
local editableMesh = AssetService:CreateEditableMesh()
-- 從資產 ID 創建可編輯網格
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID))
end)
-- 從其他可編輯的網格創建可編輯的網格
local editableMeshFromAnother = nil
local success, errorMessage = pcall(function()
editableMeshFromAnother = AssetService:CreateEditableMeshAsync(Content.fromObject(OTHER_EDITABLE_MESH))
end)
-- 從網格零件創建可編輯網格
local editableMeshFromMeshPart = nil
local success, errorMessage = pcall(function()
editableMeshFromMeshPart = AssetService:CreateEditableMeshAsync(MESH_PART.MeshContent)
end)
當它與新的 EditableMesh 鏈接時,會在 MeshPart 中顯示一個 AssetService:CreateMeshPartAsync() 。您可以創建更多 引用相同 的實例,或通過 鏈接到現有的 。
local AssetService = game:GetService("AssetService")
local Workspace = game:GetService("Workspace")
-- 從資產 ID 創建可編輯網格
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID))
end)
-- 創建新的網格零件,與可編輯網格鏈接
local newMeshPart = nil
local success, errorMessage = pcall(function()
newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMeshFromAsset))
end)
-- 或者,將上面創建的新 MeshPart 鏈接到現有的 MeshPart
local existingMeshPart = Workspace:FindFirstChild("EXISTING_MESH_PART")
existingMeshPart:ApplyMesh(newMeshPart)
要重新計算碰撞和液體幾何圖形後編輯,您可以再次呼叫 AssetService:CreateMeshPartAsync() 和 MeshPart:ApplyMesh() 來更新現有的 MeshPart 。一般來說,在概念編輯結束之後執行此操作,而不是在個別調用操作方法來操作幾何圖形之後執行此操作。網格的視覺變化總是會立即反映在引擎上,無需呼叫 AssetService:CreateMeshPartAsync() 。
固定尺寸網格
當從現有網格資產中創建 EditableMesh 時(通過 AssetService:CreateEditableMeshAsync() ),結果的可編輯網格的尺寸固定。固定尺寸的網格在記憶體效率上更高,但您無法更改垂直邊、面或屬性的數量。只能編輯vertex特性和位置的值。
local AssetService = game:GetService("AssetService")
-- 創建無固定尺寸預設的可編輯網格
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID), {FixedSize = false})
end)
穩定的vertex/面ID
許多 EditableMesh 方法使用 vertex , 正常 , UV , 顏色 和 面部 ID。這些在 Luau 中以整數形式表示,但需要一些特殊處理。主要差異是,ID 穩定且即使其他網格部分發生變更,它們也會保持相同。例如,如果 EditableMesh 有五個邊緣 {1, 2, 3, 4, 5} ,如果你移除邊緣 4 ,那麼新的邊緣將是 {1, 2, 3, 5} 。
請注意,ID 不保證會按順序排列,數字編號可能會出現空白,因此當遍巡垂直或面時,您應該遍巡由 GetVertices() 或 GetFaces() 返回的表。
分割頂點屬性
一個 邊緣 是臉部的角落,並且鏈接臉部在一起。邊緣可以擁有多個特性:位置、正常、紫外線座標、顏色和透明度。
有時候對於所有接觸頂點的面使用相同的特性值有用,但有時候你會想要不同的面使用相同的特性值在同一個頂點上。例如,在平滑球體上,每個vertex只會有一個正常。相反,在立方體的角落,頂點將有 3 種不同的正常 (每個鄰近面的一個)。你也可以在 UV 坐標中有縫紉或在vertex顏色上發生鋒利的變化。
當創建面時,每個vertex預設會擁有每個特性中的一個:一個正常、一個UV座標和一個顏色/透明度。如果您想創建縫,您應該創建新的屬性並將它們設置在面上。例如,這段代碼會創建一個鋒利的立方體:
local AssetService = game:GetService("AssetService")
-- 給予 4 個角度 ID,添加新的正常和 2 個三角形,製作鋒利的四角
local function addSharpQuad(editableMesh, vid0, vid1, vid2, vid3)
local nid = editableMesh:AddNormal() -- 這會創建一個正常的ID,它會自動計算
local fid1 = editableMesh:AddTriangle(vid0, vid1, vid2)
editableMesh:SetFaceNormals(fid1, {nid, nid, nid})
local fid2 = editableMesh:AddTriangle(vid0, vid2, vid3)
editableMesh:SetFaceNormals(fid2, {nid, nid, nid})
end
-- 在 6 側之間的增加邊緣的立方體
local function makeSharpCube()
local editableMesh = AssetService:CreateEditableMesh()
local v1 = editableMesh:AddVertex(Vector3.new(0, 0, 0))
local v2 = editableMesh:AddVertex(Vector3.new(1, 0, 0))
local v3 = editableMesh:AddVertex(Vector3.new(0, 1, 0))
local v4 = editableMesh:AddVertex(Vector3.new(1, 1, 0))
local v5 = editableMesh:AddVertex(Vector3.new(0, 0, 1))
local v6 = editableMesh:AddVertex(Vector3.new(1, 0, 1))
local v7 = editableMesh:AddVertex(Vector3.new(0, 1, 1))
local v8 = editableMesh:AddVertex(Vector3.new(1, 1, 1))
addSharpQuad(editableMesh, v5, v6, v8, v7) -- 前
addSharpQuad(editableMesh, v1, v3, v4, v2) -- 返回
addSharpQuad(editableMesh, v1, v5, v7, v3) -- 左
addSharpQuad(editableMesh, v2, v4, v8, v6) -- 右
addSharpQuad(editableMesh, v1, v2, v6, v5) -- 底部
addSharpQuad(editableMesh, v3, v7, v8, v4) -- 顶部
editableMesh:RemoveUnused()
return editableMesh
end
彎曲
網格面有前面和後面。當繪製網格時,只有面的前部被預設繪製,雖然您可以透過設置網格的 屬性變更此情況。
面周围的邊緣點的順序決定您是否正在查看前部或後部。當邊緣以反時針方向繞過面時,面的前部可見。

FACS 位置
可動的頭使用面部動作編碼系統(FACS)。查看 FACS 姿勢參考 以獲得使用 GetFacsPoses() 和類似方法時有用的信息。
每個 FACS 姿勢由 Enum.FacsActionUnit 值指定。對於 FACS 姿勢,虛擬骨頭每個都可以有 CFrame 將網格中的初始 CFrame 在綁定姿勢中轉換為該 FACS 行動單元的姿勢的 CFrame 。所有骨頭 CFrames 都在網格的本地空間中。
這些 FACS 姿勢在動畫期間會被混合在一起。有時候,基礎姿勢的混合產生了糟糕的結果。在這些情況下,您可以使用更令人滿意的 糾正姿勢 來覆蓋特定基礎姿勢的混合,以達到更好的效果。正確的姿勢由 2 或 3 Enum.FacsActionUnit 值指定。像基礎的 FACS 姿勢一樣,對於糾正姿勢,虛擬骨頭每個都可以有一個 CFrame 將網格的初始 CFrame 在綁定姿勢中轉換為 CFrame 對應的 FACS 糾正。
限制
EditableMesh 目前有 60,000 個節點和 20,000 個三角形的限制。如果嘗試添加過多的節點或三角形,將發生錯誤。
概要
方法
新增新顏色到幾何圖形並返回穩定的顏色 ID。
新增一個新的正常到幾何圖形並返回一個穩定的正常ID。
新增網格中的新三角形,並返回穩定的面 ID。
新增新的紫外線到幾何圖形並返回穩定的紫外線ID。
新增新的vertex到幾何圖形中,並返回穩定的vertex ID。
摧毀網格。
找到網格表面上最接近的點。
找到最接近特定點在空間的vertex。
找到特定球體內的所有vertex。
返回與指定面相鄰的面列表。
返回與給定節點相鄰的垂直列表。
返回指定顏色 ID 的顏色。
返回指定顏色ID的顏色Alpha(透明度)。
返回網格的所有顏色。
返回面的顏色ID,用於面上的邊緣。
返回面的正常ID,用於面上的邊緣。
返回面的 UV ID,用於面上的邊緣。
返回面的頂點 ID。
返回網格的所有面。
返回給定的普通ID的正常向量。
返回網格的所有正常。
取得vertex的位置。
返回指定的 UV ID 的 UV 座標。
返回網格的所有 UV。
返回所有vertex點為一個穩定vertex ID列表。
返回描述穩定ID的字串,用於調試目的。
合併互相碰觸的邊點。
使用穩定的面 ID 移除一個面。
移除所有未使用的vertex、normal、UV和顏色,並返回移除的ID。
重設此普通ID以自動計算。
設置顏色為顏色標識。
設置顏色 alpha (透明度) 對應一個顏色 ID。
將面的頂點顏色設置為新的顏色標識。
將面的邊緣正常值設置為新的正常ID。
將面的vertex UV設置為新的UV ID。
將面的邊緣設置為新的邊緣ID。
設定普通ID的普通值。
在網格的本地物件空間設置vertex位置。
為 UV ID 設定 UV 座標。
將網格上所有面分為三角形。
屬性
方法
AddColor
新增新顏色到幾何圖形並返回穩定的顏色 ID。
參數
返回
新顏色的穩定顏色ID。
AddNormal
添加新的正常值到幾何圖形並返回穩定的正常ID。如果未指定正常值,則正常將自動計算。
參數
正常向量。如果未指定正常值,正常將自動計算。
返回
新正常的穩定常規 ID。
AddTriangle
新增網格中的新三角形,並返回穩定的面 ID。
參數
三角形的第一個邊緣的 ID。
三角形的第二個頂點的ID。
三角形的第三個頂點的ID。
返回
新面的穩定面 ID。
AddVertex
新增新的vertex到幾何圖形中,並返回穩定的vertex ID。
參數
網格的本地物件空間中的位置。
返回
新vertex的穩定vertex ID。
Destroy
摧毀網格的內容,立即回收使用的記憶。
返回
FindClosestPointOnSurface
找到網格表面上最接近的點。返回面 ID、在本地對象空間上的網格點,以及面內位置的極坐標。請參閱 RaycastLocal() 獲得更多關於極坐標的資訊。
參數
網格本地物件空間的點位置。
返回
面 ID 的 tuple、在本地對象空間上的網格點以及面內位置的極坐標。
FindClosestVertex
找到空間中最接近特定點的vertex並返回穩定的vertex ID。
參數
網格本地物件空間的點位置。
返回
最接近穩定垂直方向ID到指定點在空間。
FindVerticesWithinSphere
找到特定球體內的所有vertex並返回一個穩定vertex ID列表。
參數
返回
請求領域內穩定頂點ID列表。
GetAdjacentVertices
提供穩定的頂點 ID,返回一個鄰近頂點列表。

參數
圍繞垂直 ID獲得鄰近垂直。
返回
指向給定垂直ID的鄰近垂直點ID列表。
GetColorAlpha
返回指定穩定顏色 ID 的顏色 alpha(透明度)。
參數
要獲得Alpha的顏色ID。
返回
要求穩定顏色 ID 的顏色 alpha。
GetPosition
獲得網格本地物件空間中vertex的位置。
參數
穩定的vertex ID,用於獲得位置。
返回
網格本地物件空間中vertex的位置。
IdDebugString
返回描述穩定ID的字串,用於調試目的,例如 f17 或 v12 ,包含類型、ID號碼和版本。
參數
用於返回調試資訊字串的ID。
返回
用人類可讀的格式描述ID的字串。
MergeVertices
合併會碰到一起的邊緣,使用單個邊緣ID但保留其他原始特性ID。
參數
邊緣被認為相互接觸的距離。
返回
將舊的vertex ID映射到新的vertex ID以融合已合並的vertex。
RaycastLocal
投射一個光線並返回交點、面ID和球心坐標。此方法的輸入和輸出在網格的本地物件空間中。
A 球心坐標 是指在面內指定一個點為面的重量組合的 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
將面的頂點顏色設置為新的顏色標識。
參數
返回
SetFaceNormals
將面的邊緣正常值設置為新的正常ID。
參數
返回
SetFaceUVs
將面的vertex UV設置為新的UV ID。
參數
返回
SetFaceVertices
將面的邊緣設置為新的邊緣ID。
參數
返回
SetNormal
設置正常ID的正常值。這將更改使用正常ID的每個面頂點的正常值。
參數
返回
SetPosition
在網格的本地物件空間設置vertex位置。
參數
返回
Triangulate
將網格上所有面分為三角形。目前這不會做任何事情,因為只能創建三角形,但如果您的代碼依賴三角形,建議您在呼叫 AssetService:CreateEditableMeshAsync() 之後呼叫此方法。