EditableMesh
*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.
EditableMesh mengubah meshes visual yang diterapkan saat terhubung ke MeshPart , memungkinkan pencarian dan modifikasi meshes baik di Studio maupun di pengalaman.
Mengaktifkan untuk Pengalaman Terpublikasi
Untuk tujuan keamanan, menggunakan EditableMesh gagal secara default untuk pengalaman yang dipublikasikan.Untuk mengaktifkan penggunaan, Anda harus berusia 13+ dan ID diverifikasi.Setelah Anda diverifikasi, buka Pengaturan Permainan Studio, pilih Keamanan , dan aktifkan toggle Izinkan API Mesh/Gambar .
Izin
Untuk mencegah penyalahgunaan, AssetService:CreateEditableMeshAsync() hanya akan memungkinkan Anda untuk memuat dan mengedit aset mesh:
- Yang dimiliki oleh pencipta pengalaman (jika pengalaman dimiliki oleh individu).
- Yang dimiliki oleh kelompok (jika pengalaman dimiliki oleh kelompok).
- Yang dimiliki oleh pengguna Studio yang masuk (jika file tempat belum disimpan atau dipublikasikan ke Roblox).
Batas-batas Memori
Aset yang dapat diedit saat ini mahal untuk penggunaan memori.Untuk mengurangi dampaknya terhadap kinerja klien, EditableMesh memiliki anggaran memori klien yang ketat, meskipun server, Studio, dan plugin beroperasi dengan memori tak terbatas.Menggunakan FixedSize mungkin membantu Anda tetap berada dalam anggaran memori dan, dalam beberapa skenario, menghubungkan satu EditableMesh ke banyak MeshParts (multireferensi) dapat membantu dengan optimisasi memori.
Pembuatan dan Tampilan
Sebuah EditableMesh dapat dibuat dari sebuah Content yang ada dari MeshPart atau ID mesh menggunakan AssetService:CreateEditableMeshAsync() , atau kosong EditableMesh dapat dibuat dengan AssetService:CreateEditableMesh() .Kemudian dapat ditampilkan, dimodifikasi, dan model tabrakannya diperbarui.Tidak semua langkah diperlukan; misalnya, Anda mungkin ingin membuat EditableMesh hanya untuk raycast tanpa pernah menampilkannya.
local AssetService = game:GetService("AssetService")
-- Buat EditableMesh kosong
local editableMesh = AssetService:CreateEditableMesh()
-- Buat EditableMesh dari ID aset
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID))
end)
-- Buat EditableMesh dari EditableMesh lain
local editableMeshFromAnother = nil
local success, errorMessage = pcall(function()
editableMeshFromAnother = AssetService:CreateEditableMeshAsync(Content.fromObject(OTHER_EDITABLE_MESH))
end)
-- Buat EditableMesh dari MeshPart
local editableMeshFromMeshPart = nil
local success, errorMessage = pcall(function()
editableMeshFromMeshPart = AssetService:CreateEditableMeshAsync(MESH_PART.MeshContent)
end)
Sebuah EditableMesh ditampilkan saat terhubung ke MeshPart baru, melalui AssetService:CreateMeshPartAsync() .Anda dapat membuat lebih banyak instansi yang merujuk pada yang sama , atau tautkan ke yang ada melalui .
local AssetService = game:GetService("AssetService")
local Workspace = game:GetService("Workspace")
-- Buat EditableMesh dari ID aset
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID))
end)
-- Buat MeshPart baru yang terhubung ke EditableMesh
local newMeshPart = nil
local success, errorMessage = pcall(function()
newMeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMeshFromAsset))
end)
-- Alternatifnya, hubungkan MeshPart baru yang dibuat di atas ke MeshPart yang ada
local existingMeshPart = Workspace:FindFirstChild("EXISTING_MESH_PART")
existingMeshPart:ApplyMesh(newMeshPart)
Untuk menghitung ulang kolisi dan geometri cairan setelah diedit, Anda dapat sekali lagi memanggil AssetService:CreateMeshPartAsync() dan MeshPart:ApplyMesh() untuk memperbarui MeshPart yang ada.Umumnya disarankan untuk melakukan ini pada akhir edit konsep, bukan setelah panggilan individu ke metode yang memanipulasi geometri.Perubahan visual pada mesh akan selalu segera dicerminkan oleh mesin, tanpa perlu memanggil AssetService:CreateMeshPartAsync() .
Mesh Ukuran Tetap
Saat membuat EditableMesh dari aset mesh yang ada (melalui AssetService:CreateEditableMeshAsync() ), mesh yang dihasilkan memiliki ukuran tetap secara default.Meshes ukuran tetap lebih efisien dalam hal memori tetapi Anda tidak dapat mengubah jumlah vertiks, wajah, atau atribut.Hanya nilai atribut vertex dan posisi yang dapat diedit.
local AssetService = game:GetService("AssetService")
-- Buat EditableMesh tanpa default ukuran tetap
local editableMeshFromAsset = nil
local success, errorMessage = pcall(function()
editableMeshFromAsset = AssetService:CreateEditableMeshAsync(Content.fromAssetId(ASSET_ID), {FixedSize = false})
end)
ID Vertex/Wajah Stabil
Banyak metode EditableMesh banyak mengambil vertex , normal , UV , warna dan wajah ID.Ini diwakili sebagai bilangan bulat di Luau tetapi mereka membutuhkan penanganan khusus.Perbedaan utama adalah bahwa ID tetap stabil dan tetap sama bahkan jika bagian lain dari mesh berubah.Sebagai contoh, jika sebuah EditableMesh memiliki lima vertiks {1, 2, 3, 4, 5} dan Anda menghapus vertiks 4 , vertiks baru akan menjadi {1, 2, 3, 5} .
Perhatikan bahwa ID tidak dijamin berada dalam urutan dan mungkin ada lubang dalam penomoran, jadi saat mengulang melalui vertex atau wajah, Anda harus mengulang melalui tabel yang dikembalikan oleh GetVertices() atau GetFaces() .
Atribut Vertex Terbagi
Sebuah vertex adalah sudut wajah, dan terhubung secara topologis wajah bersama-sama.Vertiks dapat memiliki beberapa atribut: posisi, normal, koordinat UV, warna, dan transparansi.
Terkadang berguna untuk semua wajah yang menyentuh vertex untuk menggunakan nilai atribut yang sama, tetapi terkadang Anda akan ingin wajah yang berbeda menggunakan nilai atribut yang berbeda di vertex yang sama.Sebagai contoh, pada bola mulus, setiap vertex hanya akan memiliki satu normal.Sebaliknya, di sudut kubus, vertex akan memiliki 3 normal yang berbeda (satu untuk setiap wajah berdekatan).Anda juga dapat memiliki celah di koordinat UV atau perubahan tajam pada warna vertex.
Saat membuat wajah, setiap vertex akan secara default memiliki satu dari setiap atribut: satu normal, satu koordinat UV, dan satu warna/transparansi.Jika Anda ingin membuat celah, Anda harus membuat atribut baru dan menetapkannya di wajah.Sebagai contoh, kode ini akan membuat kubus tajam:
local AssetService = game:GetService("AssetService")
-- Dengan diberikan 4 ID sudut, menambahkan normal baru dan 2 segi tiga, membuat quad tajam
local function addSharpQuad(editableMesh, vid0, vid1, vid2, vid3)
local nid = editableMesh:AddNormal() -- Ini membuat ID normal yang dihitung secara otomatis
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
-- Membuat kubus dengan tepi yang meningkat di antara 6 sisi
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) -- Depan
addSharpQuad(editableMesh, v1, v3, v4, v2) -- Kembali
addSharpQuad(editableMesh, v1, v5, v7, v3) -- Terpisah
addSharpQuad(editableMesh, v2, v4, v8, v6) -- Tepat
addSharpQuad(editableMesh, v1, v2, v6, v5) -- Bawah
addSharpQuad(editableMesh, v3, v7, v8, v4) -- Atas
editableMesh:RemoveUnused()
return editableMesh
end
Memutar
Wajah mesh memiliki sisi depan dan sisi belakang.Saat menarik meshes, hanya bagian depan wajah yang ditarik secara default, meskipun Anda dapat mengubah ini dengan mengatur properti meshes' DoubleSided ke true.
Pesanan vertiks di sekitar wajah menentukan apakah Anda melihat ke depan atau ke belakang.Bagian depan wajah terlihat saat vertex berjalan searah jam terbalik di sekitarnya.

Posisi FACS
Kepala yang dapat dianimasikan menggunakan Sistem Koding Aksi Wajah (FACS).Lihat referensi posisi FACS untuk informasi berguna saat menggunakan GetFacsPoses() dan metode serupa.
Setiap posisi FACS diberi kode oleh nilai Enum.FacsActionUnit .Untuk posisi FACS, tulang virtual masing-masing dapat memiliki CFrame yang mengubah tulang awal CFrame dalam posisi ikatan jaring ke posisi CFrame untuk unit aksi FACS itu.Semua tulang CFrames berada di ruang lokal mesh.
Posisi FACS ini dicampur bersama selama animasi.Terkadang, pencampuran posisi dasar menghasilkan hasil buruk.Dalam kasus tersebut, Anda dapat menggantikan pencampuran kombinasi spesifik posisi dasar dengan posisi korektif yang lebih menyenangkan.Posisi korektif ditentukan oleh 2 atau 3 nilai Enum.FacsActionUnit .Seperti posisi FACS dasar, untuk posisi korektif, tulang virtual masing-masing dapat memiliki CFrame yang mengubah CFrame awal tulang dalam posisi bind mesh ke CFrame untuk FACS korektif itu.
Keterbatasan
EditableMesh saat ini memiliki batas 60.000 vertex dan 20.000 segi tiga. Mencoba menambahkan terlalu banyak vertex atau segi tiga akan menyebabkan kesalahan.
Rangkuman
Properti
Kembalikan true jika mesh adalah ukuran tetap.
Metode
Menambahkan warna baru ke geometri dan mem返ikan ID warna yang stabil.
Menambahkan normal baru ke geometri dan mengembalikan ID normal yang stabil.
Menambahkan segi tiga baru ke mesh dan mengembalikan ID wajah yang stabil.
Menambahkan UV baru ke geometri dan mem返ikan ID UV yang stabil.
Menambahkan vertex baru ke geometri dan mengembalikan ID vertex yang stabil.
Menghancurkan mesh.
Menemukan titik terdekat di permukaan mesh.
Menemukan vertex terdekat ke titik tertentu di ruang.
Menemukan semua vertex dalam bidang tertentu.
Kembalikan daftar wajah yang berdekatan dengan wajah tertentu.
Kembalikan daftar vertiks yang berdekatan dengan vertex tertentu.
Kembalikan warna untuk ID warna yang diberikan.
Kembalikan warna alfa (transparansi) pada ID warna yang diberikan.
Kembalikan semua warna dari mesh.
Kembalikan ID warna wajah untuk vertikal di wajah.
Kembalikan ID normal wajah untuk vertikal di wajah.
Kembalikan ID UV wajah untuk vertikal di wajah.
Kembalikan ID vertiks wajah.
Kembalikan semua wajah dari mesh.
Kembalikan vektor normal untuk ID normal yang diberikan.
Kembalikan semua normal dari mesh.
Mendapatkan posisi vertex.
Kembali koordinat UV pada UV ID yang diberikan.
Kembalikan semua UV dari mesh.
Kembalikan semua vertex sebagai daftar vertex ID yang stabil.
Kembalikan string yang menggambarkan ID stabil, berguna untuk tujuan debugging.
Gabungkan vertex yang menyentuh bersama.
Menghapus wajah menggunakan ID wajah stabilnya.
Menghapus semua vertex yang tidak digunakan, normal, UV, dan warna, dan mengembalikan ID yang dihapus.
Setel ulang ID normal ini untuk dihitung secara otomatis.
Tetapkan warna untuk ID warna.
Tetapkan warna alfa (transparansi) untuk ID warna.
Atur warna vertiks wajah ke ID warna baru.
Atur normalitas vertiks wajah ke ID normal baru.
Atur vertex UV wajah ke ID UV baru.
Atur vertex wajah ke ID vertex baru.
Tetapkan normal untuk ID normal.
Mengatur posisi vertex di ruang objek lokal meshes.
Mengatur koordinat UV untuk ID UV.
Membagi semua wajah di mesh menjadi segi tiga.
Properti
FixedSize
Metode
AddColor
Parameter
Memberikan nilai
AddTriangle
Parameter
Memberikan nilai
Destroy
Memberikan nilai
FindVerticesWithinSphere
Parameter
Memberikan nilai
RaycastLocal
Parameter
Memberikan nilai
Contoh Kode
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