EditableMesh

顯示已棄用項目

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

無法建立

EditableMesh 將變更應用的視覺網格,當連接到 MeshPart 時,可以在 Studio 和體驗中查詢和修改網格。

啟用已發布的體驗

為了安全目的,使用 EditableMesh 對發布的體驗會預設失敗。要啟用使用,您必須年滿 13 歲且身份驗證通過。驗證通過後,開啟 Studio的遊戲設定,選擇 安全 ,並啟用 允許網格/圖像API 切換。

許可

為了防止濫用,AssetService:CreateEditableMeshAsync()只允許您載入和編輯網格資產:

  • 這些是屬於體驗創作者的(如果體驗屬於個人)。
  • 屬於群組所有的(如果體驗屬於群組)。
  • 屬於登入的工作室用戶所擁有(如果位置檔案尚未儲存或發布到 Roblox)。

記憶限制

可編輯的資產目前對記憶使用成本高昂。為了減少對客戶端性能的影響,EditableMesh 有嚴格的客戶端記憶預算,雖然伺服器、Studio 和插件都使用無限記憶。使用 FixedSize 可能會幫助您保持在記憶預算內,在某些情況下,將一個 EditableMesh 連接到多個 MeshParts (多重參考) 可能會幫助記憶優化。

創建和顯示

一個 EditableMesh 可以從現有的 ContentMeshPart 或網格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

彎曲

網格面有前面和後面。當繪製網格時,只有面的前部被預設繪製,雖然您可以透過設置網格的 屬性變更此情況。

面周围的邊緣點的順序決定您是否正在查看前部或後部。當邊緣以反時針方向繞過面時,面的前部可見。

Order of the vertices around the face

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 個三角形的限制。如果嘗試添加過多的節點或三角形,將發生錯誤。

概要

屬性

  • 唯讀
    未複製
    Roblox 安全性
    平行讀取

    如果網格是固定尺寸,返回 true 如果網格是固定尺寸。

方法

屬性

FixedSize

唯讀
未複製
Roblox 安全性
平行讀取

方法

AddColor

參數

color: Color3
預設值:""
alpha: number
預設值:""

返回

AddNormal

參數

normal: Vector3
預設值:""

返回

AddTriangle

參數

vertexId0: number
預設值:""
vertexId1: number
預設值:""
vertexId2: number
預設值:""

返回

AddUV

參數

預設值:""

返回

AddVertex

參數

預設值:""

返回

Destroy

()

返回

()

FindClosestPointOnSurface

參數

point: Vector3
預設值:""

返回

FindClosestVertex

參數

toThisPoint: Vector3
預設值:""

返回

FindVerticesWithinSphere

參數

center: Vector3
預設值:""
radius: number
預設值:""

返回

GetAdjacentFaces

參數

faceId: number
預設值:""

返回

GetAdjacentVertices

參數

vertexId: number
預設值:""

返回

GetCenter


返回

GetColor

參數

colorId: number
預設值:""

返回

GetColorAlpha

參數

colorId: number
預設值:""

返回

GetColors


返回

GetFaceColors

參數

faceId: number
預設值:""

返回

GetFaceNormals

參數

faceId: number
預設值:""

返回

GetFaceUVs

參數

faceId: number
預設值:""

返回

GetFaceVertices

參數

faceId: number
預設值:""

返回

GetFaces


返回

GetNormal

參數

normalId: number
預設值:""

返回

GetNormals


返回

GetPosition

參數

vertexId: number
預設值:""

返回

GetSize


返回

GetUV

參數

uvId: number
預設值:""

返回

GetUVs


返回

GetVertices


返回

IdDebugString

參數

id: number
預設值:""

返回

MergeVertices

Map

參數

mergeTolerance: number
預設值:""

返回

Map

RaycastLocal

參數

origin: Vector3
預設值:""
direction: Vector3
預設值:""

返回

範例程式碼

EditableMesh:RaycastLocal()

local AssetService = game:GetService("AssetService")
local Workspace = game:GetService("Workspace")
-- 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
warn(errorMsg)
end
-- Function that will cast a ray from the given point, returning the world point of the hit and the UV coordinate
local function castRayFromCamera(meshPart: MeshPart, editableMesh: EditableMesh, viewportPoint: Vector3)
if not meshPart then
return
end
-- Calculate how much the object is being scaled in each dimension
local renderScale = meshPart.Size / meshPart.MeshSize
-- Create ray from camera along the direction of a clicked point
local ray = Workspace.CurrentCamera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y)
-- Convert to object space to use with RaycastLocal()
local relativeOrigin = meshPart.CFrame:PointToObjectSpace(ray.Origin) / renderScale
local relativeTarget = meshPart.CFrame:PointToObjectSpace(ray.Origin + ray.Direction * 100) / renderScale
local relativeDirection = relativeTarget - relativeOrigin
local faceId, point, barycentricCoordinate, vertId1, vertId2, vertId3 =
editableMesh:RaycastLocal(relativeOrigin, relativeDirection)
if not faceId then
-- Didn't hit any faces
return
end
-- Compute the hit point in world space
local worldHitPoint = meshPart.CFrame:PointToWorldSpace(point * renderScale)
-- Get the UVs on the face
local uvId1 = editableMesh:GetVertexFaceUV(vertId1, faceId)
local uvId2 = editableMesh:GetVertexFaceUV(vertId2, faceId)
local uvId3 = editableMesh:GetVertexFaceUV(vertId3, faceId)
local uv1 = editableMesh:GetUV(uvId1)
local uv2 = editableMesh:GetUV(uvId2)
local uv3 = editableMesh:GetUV(uvId3)
-- Interpolate UVs within the face based on the barycentric coordinate
local u = (barycentricCoordinate.x * uv1.x) + (barycentricCoordinate.y * uv2.x) + (barycentricCoordinate.z * uv3.x)
local v = (barycentricCoordinate.x * uv1.y) + (barycentricCoordinate.y * uv2.y) + (barycentricCoordinate.z * uv3.y)
return worldHitPoint, Vector2.new(u, v)
end

RemoveFace

()

參數

faceId: number
預設值:""

返回

()

RemoveUnused


返回

ResetNormal

()

參數

normalId: number
預設值:""

返回

()

SetColor

()

參數

colorId: number
預設值:""
color: Color3
預設值:""

返回

()

SetColorAlpha

()

參數

colorId: number
預設值:""
alpha: number
預設值:""

返回

()

SetFaceColors

()

參數

faceId: number
預設值:""
ids: Array
預設值:""

返回

()

SetFaceNormals

()

參數

faceId: number
預設值:""
ids: Array
預設值:""

返回

()

SetFaceUVs

()

參數

faceId: number
預設值:""
ids: Array
預設值:""

返回

()

SetFaceVertices

()

參數

faceId: number
預設值:""
ids: Array
預設值:""

返回

()

SetNormal

()

參數

normalId: number
預設值:""
normal: Vector3
預設值:""

返回

()

SetPosition

()

參數

vertexId: number
預設值:""
預設值:""

返回

()

SetUV

()

參數

uvId: number
預設值:""
預設值:""

返回

()

Triangulate

()

返回

()

活動