Meningkatkan kinerja

*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.

Halaman ini menjelaskan masalah kinerja umum dan praktik terbaik untuk menguranginya.

Perhitungan skrip

Operasi yang mahal dalam kode Luau memerlukan waktu lebih lama untuk diproses dan dapat mempengaruhi laju bingkai. Kecuali jika dieksekusi secara paralel, kode Luau berjalan secara sinkron dan memblokir utas utama hingga menemukan fungsi yang menghasilkan utas.

Masalah umum

  • Operasi intensif pada struktur tabel - Operasi kompleks seperti serialisasi, deserialisasi, dan kloning mendalam memerlukan biaya kinerja yang tinggi, terutama pada struktur tabel besar. Ini terutama berlaku jika operasi ini bersifat rekursif atau melibatkan iterasi pada struktur data yang sangat besar.
  • Peristiwa frekuensi tinggi - Mengaitkan operasi mahal dengan peristiwa berbasis bingkai dari RunService tanpa membatasi frekuensi berarti operasi ini diulang setiap bingkai, yang sering kali mengakibatkan peningkatan waktu perhitungan yang tidak perlu. Peristiwa ini termasuk:

Mitigasi

  • Panggil kode pada peristiwa RunService dengan hemat, membatasi penggunaan pada kasus di mana pemanggilan frekuensi tinggi sangat penting (misalnya, memperbarui kamera). Anda dapat mengeksekusi sebagian besar kode lainnya di peristiwa lain atau kurang sering dalam sebuah loop.
  • Pecah tugas besar atau mahal menggunakan task.wait() untuk menyebarkan pekerjaan di beberapa bingkai.
  • Identifikasi dan optimalkan operasi yang tidak perlu mahal dan gunakan multithreading untuk tugas yang mahal secara komputasi yang tidak perlu mengakses model data.
  • Skrip sisi server tertentu dapat memanfaatkan generasi kode asli, sebuah flag sederhana yang mengkompilasi skrip menjadi kode mesin daripada bytecode.
  • Jika server Anda masih kehabisan CPU setelah Anda mengoptimalkan, Anda dapat memesan lebih banyak dengan Layanan Diperluas untuk Komputasi.

Ruang lingkup MicroProfiler

Ruang lingkupPerhitungan terkait
RunService.PreRenderKode yang dieksekusi pada peristiwa PreRender
RunService.PreSimulationKode yang dieksekusi pada peristiwa Stepped
RunService.PostSimulationKode yang dieksekusi pada peristiwa Heartbeat
RunService.HeartbeatKode yang dieksekusi pada peristiwa Heartbeat

Untuk informasi lebih lanjut tentang debugging skrip menggunakan MicroProfiler, lihat pustaka debug, yang mencakup fungsi untuk menandai kode tertentu dan meningkatkan spesifikasi lebih lanjut, seperti debug.profilebegin dan debug.profileend. Banyak metode API Roblox yang dipanggil oleh skrip juga memiliki tag MicroProfiler terkait yang dapat memberikan sinyal yang berguna.

Penggunaan memori skrip

Kebocoran memori dapat terjadi ketika Anda menulis skrip yang mengkonsumsi memori yang tidak dapat dibebaskan dengan benar oleh pengumpul sampah ketika tidak lagi digunakan. Kebocoran ini khususnya merajalela di server, karena mereka dapat terus online selama berhari-hari, sedangkan sesi klien jauh lebih pendek.

Nilai memori berikut di Konsol Pengembang dapat menunjukkan masalah yang memerlukan penyelidikan lebih lanjut:

  • LuaHeap - Konsumsi yang tinggi atau meningkat menunjukkan kebocoran memori.
  • InstanceCount - Jumlah instance yang terus meningkat menunjukkan referensi ke beberapa instance dalam kode Anda tidak dibersihkan oleh pengumpul sampah.
  • PlaceScriptMemory - Menyediakan rincian penggunaan memori per skrip.

Masalah umum

  • Meninggalkan koneksi terhubung - Mesin tidak pernah mengumpulkan sampah peristiwa yang terhubung ke instance dan nilai apa pun yang dirujuk di dalam callback yang terhubung. Oleh karena itu, koneksi aktif dari peristiwa dan kode di dalam instance yang terhubung, fungsi yang terhubung, dan nilai yang dirujuk, berada di luar jangkauan pengumpul sampah memori, bahkan setelah peristiwa dipicu.

    Meskipun peristiwa terputus ketika instance yang mereka miliki dihancurkan, kesalahan umum adalah mengasumsikan ini berlaku untuk objek Player. Setelah seorang pengguna meninggalkan permainan, mesin tidak secara otomatis menghancurkan objek Player dan model karakter perwakilan mereka, sehingga koneksi ke objek Player dan instance di bawah model karakter, seperti CharacterAdded, masih mengkonsumsi memori jika Anda tidak memutuskan koneksi mereka dalam skrip Anda. Ini dapat mengakibatkan kebocoran memori yang sangat signifikan seiring waktu di server saat ratusan pengguna bergabung dan meninggalkan permainan.

  • Tabel - Menyisipkan objek ke dalam tabel tetapi tidak menghapusnya ketika tidak lagi diperlukan menyebabkan konsumsi memori yang tidak perlu, terutama untuk tabel yang melacak data pengguna saat mereka bergabung. Misalnya, contoh kode berikut membuat tabel yang menambahkan informasi pengguna setiap kali seorang pengguna bergabung:

    Contoh
    local playerInfo = {}
    Players.PlayerAdded:Connect(function(player)
    playerInfo[player] = {} -- beberapa info
    end)

    Jika Anda tidak menghapus entri ini ketika tidak lagi diperlukan, tabel terus tumbuh dalam ukuran dan mengkonsumsi lebih banyak memori saat lebih banyak pengguna bergabung dalam sesi. Kode apa pun yang mengiterasi tabel ini juga menjadi lebih mahal secara komputasi seiring pertumbuhan ukuran tabel.

Mitigasi

Untuk membersihkan semua nilai yang digunakan untuk mencegah kebocoran memori:

  • Putuskan semua koneksi - Telusuri basis kode Anda dan pastikan setiap koneksi dibersihkan melalui salah satu jalur berikut:

    • Memutuskan secara manual menggunakan fungsi Disconnect().
    • Menghancurkan instance yang dimiliki peristiwa dengan fungsi Destroy().
    • Menghancurkan objek skrip yang menghubungkan kembali ke koneksi.
  • Hapus objek pemain dan karakter setelah meninggalkan - Aktifkan Workspace.PlayerCharacterDestroyBehavior untuk secara otomatis menghancurkan objek pemain dan model karakter setelah seorang pengguna meninggalkan. Jika Anda mau, Anda dapat membersihkannya secara manual:

    Contoh pembersihan pemain dan karakter
    local Players = game:GetService("Players")
    Players.PlayerAdded:Connect(function(player)
    player.CharacterRemoving:Connect(function(character)
    task.defer(character.Destroy, character)
    end)
    end)
    Players.PlayerRemoving:Connect(function(player)
    task.defer(player.Destroy, player)
    end)

Perhitungan fisika

Simulasi fisika yang berlebihan dapat menjadi penyebab utama peningkatan waktu perhitungan per bingkai di server dan klien.

Masalah umum

  • Frekuensi langkah fisika yang berlebihan - Secara default, perilaku langkah berada dalam mode adaptif, di mana fisika melangkah pada 60 Hz, 120 Hz, atau 240 Hz, tergantung pada kompleksitas mekanisme fisika.

    Mode tetap dengan akurasi fisika yang lebih baik juga tersedia, yang memaksa semua perakitan fisika untuk melangkah pada 240 Hz (empat kali per bingkai). Ini mengakibatkan perhitungan yang jauh lebih banyak setiap bingkai.

  • Jumlah objek yang disimulasikan yang berlebihan - Semakin banyak perakitan 3D yang disimulasikan, semakin lama perhitungan fisika memakan waktu setiap bingkai. Seringkali, permainan akan memiliki objek yang disimulasikan yang tidak perlu disimulasikan atau akan memiliki mekanisme yang memiliki lebih banyak batasan dan sambungan daripada yang mereka butuhkan.

  • Deteksi tabrakan yang terlalu tepat - Bagian mesh memiliki properti CollisionFidelity untuk mendeteksi tabrakan yang menawarkan berbagai mode dengan tingkat dampak kinerja yang berbeda. Mode deteksi tabrakan yang tepat untuk bagian mesh memiliki biaya kinerja yang paling mahal dan memerlukan waktu lebih lama bagi mesin untuk menghitung.

Mitigasi

  • Jepit bagian yang tidak memerlukan simulasi - Jepit semua bagian yang tidak perlu digerakkan oleh fisika, seperti untuk NPC statis.

  • Gunakan langkah fisika adaptif - Langkah adaptif secara dinamis menyesuaikan laju perhitungan fisika untuk mekanisme fisika, memungkinkan pembaruan fisika dilakukan kurang sering dalam beberapa kasus.

  • Kurangi kompleksitas mekanisme

    • Di mana mungkin, minimalkan jumlah batasan fisika atau sambungan dalam sebuah perakitan.
    • Kurangi jumlah tabrakan diri dalam sebuah mekanisme, seperti dengan menerapkan batasan atau batasan tanpa tabrakan pada anggota ragdoll untuk mencegah mereka bertabrakan satu sama lain.
  • Kurangi penggunaan ketepatan tabrakan yang tepat untuk mesh

    • Untuk objek kecil atau tidak dapat berinteraksi di mana pengguna jarang memperhatikan perbedaan, gunakan ketepatan kotak.

    • Untuk objek kecil-sedang, gunakan ketepatan kotak atau hull, tergantung pada bentuknya.

    • Untuk objek besar dan sangat kompleks, bangun tabrakan kustom menggunakan bagian tak terlihat jika memungkinkan.

    • Untuk objek yang tidak memerlukan tabrakan, nonaktifkan tabrakan dan gunakan ketepatan kotak atau hull, karena geometri tabrakan masih disimpan dalam memori.

    • Anda dapat merender geometri tabrakan untuk tujuan debug di Studio dengan mengaktifkan Ketepatan tabrakan dari widget Opsi Visualisasi di sudut kanan atas viewport 3D.

      Sebagai alternatif, Anda dapat menerapkan filter CollisionFidelity=PreciseConvexDecomposition ke Explorer yang menunjukkan jumlah semua bagian mesh dengan ketepatan yang tepat dan memungkinkan Anda untuk dengan mudah memilihnya.

    • Untuk panduan mendalam tentang cara memilih opsi ketepatan tabrakan yang seimbang antara kebutuhan ketepatan dan kinerja Anda, lihat Atur parameter fisika dan rendering.

Ruang lingkup MicroProfiler

Ruang lingkupPerhitungan terkait
physicsSteppedPerhitungan fisika keseluruhan
worldStepLangkah fisika diskrit yang diambil setiap bingkai

Penggunaan memori fisika

Gerakan fisika dan deteksi tabrakan mengkonsumsi memori. Bagian mesh memiliki properti CollisionFidelity yang menentukan pendekatan yang digunakan untuk mengevaluasi batas tabrakan dari mesh.

Masalah umum

Mode deteksi tabrakan default dan tepat mengkonsumsi memori yang jauh lebih banyak daripada dua mode lainnya dengan bentuk tabrakan yang lebih rendah.

Jika Anda melihat tingkat konsumsi memori yang tinggi di bawah PhysicsParts, Anda mungkin perlu menjelajahi pengurangan ketepatan tabrakan objek dalam permainan Anda.

Cara mengurangi

Untuk mengurangi memori yang digunakan untuk ketepatan tabrakan:

  • Untuk bagian yang tidak memerlukan tabrakan, nonaktifkan tabrakan mereka dengan mengatur BasePart.CanCollide, BasePart.CanTouch, dan BasePart.CanQuery ke false.
  • Kurangi ketepatan tabrakan menggunakan pengaturan CollisionFidelity. Box memiliki overhead memori terendah, dan Default dan Precise umumnya lebih mahal.
    • Umumnya aman untuk mengatur ketepatan tabrakan bagian kecil yang dijepit ke Box.
    • Untuk mesh besar yang sangat kompleks, Anda mungkin ingin membangun mesh tabrakan Anda sendiri dari objek yang lebih kecil dengan ketepatan tabrakan kotak.

Humanoid

Humanoid adalah kelas yang menyediakan berbagai fungsi untuk karakter pemain dan non-pemain (NPC). Meskipun kuat, Humanoid memiliki biaya perhitungan yang signifikan.

Masalah umum

  • Meninggalkan semua HumanoidStateTypes diaktifkan pada NPC - Ada biaya kinerja untuk meninggalkan HumanoidStateTypes tertentu diaktifkan. Nonaktifkan yang tidak diperlukan untuk NPC Anda. Misalnya, kecuali NPC Anda akan memanjat tangga, aman untuk menonaktifkan status Climbing.
  • Menginstansiasi, memodifikasi, dan menghidupkan kembali model dengan Humanoids atau MeshParts yang terkulai secara sering
    • Ini bisa intensif untuk diproses oleh mesin, terutama jika model ini menggunakan pakaian berlapis. Ini juga bisa menjadi masalah khusus dalam permainan di mana avatar sering respawn.
    • Di MicroProfiler, tag updateInvalidatedFastClusters yang panjang (lebih dari 4 ms) sering menjadi sinyal bahwa instansiasi/modifikasi avatar memicu invalidasi yang berlebihan.
  • Menggunakan Humanoids dalam kasus di mana mereka tidak diperlukan - NPC statis yang tidak bergerak umumnya tidak memerlukan kelas Humanoid.
  • Memutar animasi pada sejumlah besar NPC dari server - Animasi NPC yang berjalan di server perlu disimulasikan di server dan direplikasi ke klien. Ini bisa menjadi beban yang tidak perlu.
  • Melakukan perubahan ukuran dan skala yang tidak perlu - Perubahan ukuran/skala menyebabkan FastCluster dibangun kembali. Cobalah untuk mengurangi ini selama gameplay jika Anda melihat masalah kinerja terkait FastCluster. Demikian pula, perubahan properti lainnya juga dapat menyebabkan FastCluster dibangun kembali, jadi secara umum kurangi perubahan ini sebanyak mungkin.

Mitigasi

  • Putar animasi NPC di klien - Dalam permainan dengan sejumlah besar NPC, pertimbangkan untuk membuat Animator di klien dan menjalankan animasi secara lokal. Ini mengurangi beban di server dan kebutuhan untuk replikasi yang tidak perlu. Ini juga memungkinkan optimasi tambahan (seperti hanya memutar animasi untuk NPC yang dekat dengan karakter).
  • Gunakan alternatif ramah kinerja untuk Humanoids - Model NPC tidak perlu mengandung objek humanoid.
    • Untuk NPC statis, gunakan AnimationController sederhana, karena mereka tidak perlu bergerak tetapi hanya perlu memutar animasi.
    • Untuk NPC yang bergerak, pertimbangkan untuk menerapkan pengontrol gerakan Anda sendiri dan menggunakan AnimationController untuk animasi, tergantung pada kompleksitas NPC Anda.
  • Nonaktifkan status humanoid yang tidak digunakan - Gunakan Humanoid:SetStateEnabled() untuk hanya mengaktifkan status yang diperlukan untuk setiap humanoid.
  • Pooling model NPC dengan respawn yang sering - Alih-alih menghancurkan NPC sepenuhnya, kirim NPC ke kolam NPC tidak aktif. Dengan cara ini, ketika NPC baru diperlukan untuk respawn, Anda dapat dengan mudah mengaktifkan kembali salah satu NPC dari kolam. Proses ini disebut pooling, yang meminimalkan jumlah kali karakter perlu diinstansiasi.
  • Hanya spawn NPC ketika pengguna berada di dekatnya - Jangan spawn NPC ketika pengguna tidak berada dalam jangkauan, dan hapus mereka ketika pengguna meninggalkan jangkauan mereka.
  • Hindari membuat perubahan pada hierarki avatar setelah diinstansiasi - Modifikasi tertentu pada hierarki avatar memiliki implikasi kinerja yang signifikan. Beberapa optimasi tersedia:

Ruang lingkup MicroProfiler

Ruang lingkupPerhitungan terkait
stepHumanoidKontrol humanoid dan fisika
stepAnimationAnimasi humanoid dan animator
updateInvalidatedFastClustersTerhubung dengan instansiasi atau modifikasi avatar

Rendering

Sebagian besar waktu yang dihabiskan klien setiap bingkai adalah untuk merender adegan dalam bingkai saat ini. Server tidak melakukan rendering, jadi bagian ini eksklusif untuk klien.

Panggilan gambar

Panggilan gambar adalah sekumpulan instruksi dari mesin ke GPU untuk merender sesuatu. Panggilan gambar memiliki overhead yang signifikan. Umumnya, semakin sedikit panggilan gambar per bingkai, semakin sedikit waktu komputasi yang dihabiskan untuk merender sebuah bingkai.

Anda dapat melihat berapa banyak panggilan gambar yang sedang terjadi dengan item Statistik Render ⟩ Waktu di Studio. Anda dapat melihat Statistik Render di klien dengan menekan ShiftF2.

Semakin banyak objek yang perlu digambar dalam adegan Anda dalam bingkai tertentu, semakin banyak panggilan gambar yang dibuat ke GPU. Namun, Mesin Roblox memanfaatkan proses yang disebut instancing untuk menggabungkan mesh identik dengan karakteristik tekstur yang sama menjadi satu panggilan gambar. Secara khusus, beberapa mesh dengan MeshContent yang sama ditangani dalam satu panggilan gambar ketika:

Masalah umum lainnya

  • Kepadatan objek yang berlebihan - Jika sejumlah besar objek terkonsentrasi dengan kepadatan tinggi, maka merender area adegan ini memerlukan lebih banyak panggilan gambar. Jika Anda menemukan laju bingkai Anda turun saat melihat bagian tertentu dari peta, ini bisa menjadi sinyal yang baik bahwa kepadatan objek di area ini terlalu tinggi.

    Objek seperti decal, tekstur, dan partikel tidak dapat dikelompokkan dengan baik dan memperkenalkan panggilan gambar tambahan. Perhatikan jenis objek ini di dalam adegan. Secara khusus, perubahan properti pada ParticleEmitters dapat memiliki dampak dramatis pada kinerja.

  • Peluang instancing yang terlewat - Seringkali, sebuah adegan akan mencakup mesh yang sama yang diduplikasi beberapa kali, tetapi setiap salinan mesh memiliki ID aset mesh atau tekstur yang berbeda. Ini mencegah instancing dan dapat menyebabkan panggilan gambar yang tidak perlu.

    Penyebab umum dari masalah ini adalah ketika seluruh adegan diimpor sekaligus, daripada aset individu diimpor ke Roblox dan kemudian diduplikasi setelah impor untuk merakit adegan.

    Bahkan skrip sederhana seperti ini dapat membantu Anda mengidentifikasi bagian mesh dengan nama yang sama yang menggunakan ID mesh yang berbeda:

    for _,descendant in workspace:GetDescendants() do
    if descendant:IsA("MeshPart") then
    print(descendant.Name .. ", " .. descendant.MeshId)
    end
    end

    Output (dengan Stack Lines diaktifkan) mungkin terlihat seperti ini. Baris yang diulang menunjukkan penggunaan kembali mesh yang sama, yang baik. Baris unik tidak selalu buruk, tetapi tergantung pada skema penamaan Anda, bisa menunjukkan mesh duplikat dalam permainan Anda:

    LargeRock, rbxassetid://106420009602747 (x144) -- baik
    LargeRock, rbxassetid://120109824668127
    LargeRock, rbxassetid://134460273008628
    LargeRock, rbxassetid://139288987285823
    LargeRock, rbxassetid://71302144984955
    LargeRock, rbxassetid://90621205713698
    LargeRock, rbxassetid://113160939160788
    LargeRock, rbxassetid://135944592365226 -- semua kemungkinan duplikat
  • Kompleksitas objek yang berlebihan - Meskipun tidak sepenting jumlah panggilan gambar, jumlah segitiga dalam sebuah adegan mempengaruhi berapa lama sebuah bingkai memerlukan waktu untuk dirender. Adegan dengan jumlah mesh yang sangat besar dan sangat kompleks adalah masalah umum, begitu juga dengan adegan yang memiliki properti MeshPart.RenderFidelity diatur ke Precise pada terlalu banyak mesh.

  • Pembuatan bayangan yang berlebihan - Menangani bayangan adalah proses yang mahal, dan peta yang mengandung sejumlah besar dan kepadatan objek cahaya yang memancarkan bayangan (atau sejumlah besar dan kepadatan bagian kecil yang dipengaruhi oleh bayangan) dapat memiliki masalah kinerja.

  • Overdraw transparansi tinggi - Menempatkan objek dengan transparansi parsial berdekatan satu sama lain memaksa mesin untuk merender piksel yang tumpang tindih beberapa kali, yang dapat merugikan kinerja. Untuk informasi lebih lanjut tentang mengidentifikasi dan memperbaiki masalah ini, lihat Hapus transparansi berlapis.

  • Gerakan MeshPart yang tidak perlu - MeshPart yang terkulai yang merupakan bagian dari Model tanpa Humanoid dikelompokkan menggunakan FastClusters yang terorganisir secara spasial. Ketika MeshPart ini bergerak, mereka harus terus-menerus ditambahkan dan dihapus dari cluster spasial ini, memaksa cluster untuk dibangun kembali dan mempengaruhi kinerja.

    • Solusi yang sangat efektif adalah menyematkan Humanoid di dalam Model. Kehadiran Humanoid mengesampingkan perilaku pengelompokan spasial default, memaksa penggunaan satu FastCluster terpadu untuk seluruh Model. Akibatnya, pembaruan posisi tidak lagi memerlukan pembangunan kembali cluster, sehingga mengurangi bottleneck kinerja. Teknik ini harus dibatasi hanya untuk MeshPart yang diharapkan bergerak, karena dapat memperkenalkan overhead memori dan membatalkan manfaat optimasi spasial. Kami merekomendasikan untuk selalu memprofil game Anda setelah melakukan perubahan semacam ini. Lihat Tips kinerja Humanoid untuk informasi tambahan.
  • Terlalu banyak bagian dalam Model - Terlalu banyak bagian dalam Model dapat menyebabkan pembangunan kembali lebih sering karena potensi perubahan properti bagian yang memerlukan pembangunan kembali penuh. Temukan keseimbangan yang tepat dari bagian dalam Model saat menggunakan FastCluster.

Mitigasi

  • Instancing mesh identik dan mengurangi jumlah mesh unik - Jika Anda memastikan semua mesh identik memiliki ID aset yang sama, mesin dapat mengenali dan merendernya dalam satu panggilan gambar. Pastikan untuk hanya mengunggah setiap mesh dalam peta sekali dan kemudian menduplikasinya di Studio untuk digunakan kembali daripada mengimpor peta besar secara keseluruhan, yang mungkin menyebabkan mesh identik memiliki ID konten terpisah dan dikenali sebagai aset unik oleh mesin. Paket adalah mekanisme yang berguna untuk penggunaan kembali objek.
  • Culling - Culling menggambarkan proses menghilangkan panggilan gambar untuk objek yang tidak berkontribusi pada bingkai yang dirender akhir. Secara default, mesin melewatkan panggilan gambar untuk objek di luar bidang pandang kamera (frustum culling) dan bagian, mesh, dan terrain yang terhalang dari pandangan oleh objek lain (occlusion culling). Dalam skenario tertentu, seperti lingkungan dalam ruangan, Anda mungkin dapat menerapkan sistem ruangan atau portal dan secara manual mencull objek untuk lebih mengurangi panggilan gambar atau beban komputasi keseluruhan.
  • Mengurangi tingkat detail untuk model - Aktifkan streaming instance dan atur properti LevelOfDetail model dunia Anda ke SLIM untuk merender mesh SLIM ringan yang dioptimalkan untuk model saat jarak dari kamera meningkat.
  • Mengurangi tingkat detail untuk avatar - Aktifkan streaming instance dan atur Workspace.EnableSLIMAvatars untuk merender avatar platform sebagai representasi SLIM ringan yang dioptimalkan dengan dukungan animasi penuh saat jarak dari kamera meningkat.
  • Mengurangi ketepatan render - Atur MeshPart.RenderFidelity ke Automatic atau Performance. Ini memungkinkan mesh untuk kembali ke alternatif yang kurang kompleks, yang dapat mengurangi jumlah poligon yang perlu digambar.
  • Menonaktifkan pembuatan bayangan pada bagian dan objek cahaya yang sesuai - Mesin Roblox secara otomatis menurunkan kualitas bayangan saat tingkat kualitas grafis klien menurun, akhirnya menonaktifkan bayangan sepenuhnya pada tingkat kualitas di bawah 4. Namun, Anda dapat secara selektif menonaktifkan properti pembuatan bayangan pada objek cahaya dan bagian untuk meningkatkan kinerja saat bayangan diaktifkan dan meningkatkan kemungkinan bayangan tetap diaktifkan. Beberapa contoh optimasi yang dapat Anda lakukan baik pada waktu edit atau secara dinamis saat runtime:
    • Gunakan properti BasePart.CastShadow untuk menonaktifkan pembuatan bayangan pada bagian kecil di mana bayangan tidak mungkin terlihat. Strategi ini sangat efektif ketika diterapkan pada bagian yang jauh dari kamera pengguna.

    • Nonaktifkan bayangan pada objek yang bergerak jika memungkinkan.

    • Nonaktifkan Light.Shadows pada instance cahaya di mana objek tidak perlu memancarkan bayangan.

    • Batasi jangkauan dan sudut instance cahaya.

    • Gunakan lebih sedikit instance cahaya.

    • Pertimbangkan untuk menonaktifkan lampu yang berada di luar jangkauan tertentu atau berdasarkan ruangan untuk lingkungan dalam ruangan.

Ruang lingkup MicroProfiler

Ruang lingkupPerhitungan terkait
Prepare and PerformRendering keseluruhan
Perform/Scene/computeLightingPerformPembaruan grid cahaya dan bayangan
LightGridCPUPembaruan grid cahaya voxel
ShadowMapSystemPemetaan bayangan
Perform/Scene/UpdateViewPersiapan untuk rendering dan pembaruan partikel
Perform/Scene/RenderViewRendering dan pemrosesan pasca

Jaringan dan replikasi

Jaringan dan replikasi menggambarkan proses di mana data dikirim antara server dan klien yang terhubung. Informasi dikirim antara klien dan server setiap bingkai, tetapi jumlah informasi yang lebih besar memerlukan lebih banyak waktu komputasi.

Masalah umum

  • Lalu lintas jarak jauh yang berlebihan - Mengirim sejumlah besar data melalui objek RemoteEvent atau RemoteFunction atau memanggilnya sangat sering dapat menyebabkan sejumlah besar waktu CPU dihabiskan untuk memproses paket masuk setiap bingkai. Kesalahan umum termasuk:

    • Mereplikasi data setiap bingkai yang tidak perlu direplikasi.
    • Mereplikasi data pada input pengguna tanpa mekanisme untuk membatasi.
    • Mengirim lebih banyak data daripada yang diperlukan. Misalnya, mengirim seluruh inventaris pemain ketika mereka membeli item daripada hanya detail item yang dibeli.
  • Pembuatan atau penghapusan pohon instance yang kompleks - Ketika perubahan dilakukan pada model data di server, itu direplikasi ke klien yang terhubung. Ini berarti membuat dan menghancurkan hierarki instance besar seperti peta pada runtime bisa sangat intensif jaringan.

    Penyebab umum di sini adalah data animasi kompleks yang disimpan oleh plugin Animation Editor dalam rig. Jika ini tidak dihapus sebelum permainan diterbitkan dan model yang dianimasikan sering diduplikasi, sejumlah besar data akan direplikasi secara tidak perlu.

  • TweenService sisi server - Jika TweenService digunakan untuk tween objek di sisi server, properti yang tweened direplikasi ke setiap klien setiap bingkai. Ini tidak hanya mengakibatkan tween yang bergetar saat latensi klien berfluktuasi, tetapi juga menyebabkan banyak lalu lintas jaringan yang tidak perlu.

Mitigasi

Anda dapat menerapkan taktik berikut untuk mengurangi replikasi yang tidak perlu:

  • Hindari mengirim sejumlah besar data sekaligus melalui peristiwa jarak jauh. Sebagai gantinya, hanya kirim data yang diperlukan pada frekuensi yang lebih rendah. Misalnya, untuk status karakter, replikasi saat berubah daripada setiap bingkai.
  • Pecah pohon instance yang kompleks seperti peta dan muat dalam potongan untuk mendistribusikan pekerjaan mereplikasi ini di beberapa bingkai.
  • Bersihkan metadata animasi, terutama direktori animasi rig, setelah mengimpor.
  • Batasi replikasi instance yang tidak perlu, terutama dalam kasus di mana server tidak perlu mengetahui instance yang sedang dibuat. Ini termasuk:
    • Efek visual seperti ledakan atau ledakan sihir. Server hanya perlu mengetahui lokasi untuk menentukan hasilnya, sementara klien dapat membuat visual secara lokal.
    • Model tampilan item orang pertama.
    • Tween objek di klien daripada di server.

Ruang lingkup MicroProfiler

Ruang lingkupPerhitungan terkait
ProcessPacketsMemproses paket jaringan masuk, seperti pemanggilan peristiwa dan perubahan properti
Allocate Bandwidth and Run SendersPeristiwa keluar yang relevan di server

Penggunaan memori aset

Mekanisme dengan dampak tertinggi yang tersedia untuk pencipta untuk meningkatkan penggunaan memori klien adalah dengan mengaktifkan streaming instance.

Streaming instance

Streaming instance secara selektif memuat bagian dari model data yang tidak diperlukan, yang dapat menyebabkan waktu muat yang jauh lebih singkat dan meningkatkan kemampuan klien untuk mencegah kerusakan saat mengalami tekanan memori.

Jika Anda mengalami masalah memori dan streaming instance dinonaktifkan, pertimbangkan untuk memperbarui permainan Anda untuk mendukungnya, terutama jika dunia 3D Anda besar. Streaming instance didasarkan pada jarak dalam ruang 3D, jadi dunia yang lebih besar secara alami mendapatkan manfaat lebih banyak darinya.

Jika streaming instance diaktifkan, Anda dapat meningkatkan agresivitasnya. Misalnya, pertimbangkan:

  • Mengurangi penggunaan Enum.ModelStreamingMode.Persistent jika memungkinkan. Anda mungkin perlu memperbarui skrip Anda jika Anda menggunakannya sebagai langkah kompatibilitas.
  • Mengurangi Workspace.StreamingMinRadius dan Workspace.StreamingTargetRadius.

Untuk informasi lebih lanjut tentang opsi streaming dan manfaatnya, lihat properti streaming.

Masalah umum lainnya

  • Duplikasi aset - Kesalahan umum adalah mengunggah aset yang sama beberapa kali yang mengakibatkan ID aset yang berbeda. Ini dapat menyebabkan konten yang sama dimuat ke dalam memori beberapa kali.

  • Volume aset yang berlebihan - Bahkan ketika aset tidak identik, ada kasus ketika peluang untuk menggunakan kembali aset yang sama dan menghemat memori terlewatkan.

  • File audio - File audio dapat menjadi kontributor yang mengejutkan untuk penggunaan memori, terutama jika Anda memuat semuanya ke dalam klien sekaligus daripada hanya memuat apa yang Anda butuhkan untuk sebagian permainan. Untuk strategi, lihat Waktu muat.

  • Tekstur resolusi tinggi - Konsumsi memori grafis untuk tekstur tidak terkait dengan ukuran tekstur di disk; jumlah piksel dalam tekstur menentukan penggunaan memori. Misalnya, tekstur 1024x1024 piksel mengkonsumsi empat kali lipat memori grafis dari tekstur 512x512.

    Gambar yang diunggah ke Roblox ditranskode ke format tetap, jadi tidak ada manfaat memori untuk mengunggah gambar dalam model warna yang terkait dengan lebih sedikit byte per piksel. Demikian pula, mengompresi gambar sebelum diunggah atau menghapus saluran alfa dari gambar yang tidak membutuhkannya dapat mengurangi ukuran gambar di disk, tetapi tidak meningkatkan penggunaan memori.

    Saat permainan dimuat, mesin secara otomatis memulai dengan tekstur berkualitas lebih rendah dan kemudian meningkatkan kualitas berdasarkan memori perangkat yang tersedia, jarak dari kamera, jumlah ruang layar yang diambil oleh tekstur, dan faktor lainnya. Meskipun demikian, secara strategis mengatur ukuran tekstur Anda dapat meningkatkan penggunaan memori dalam permainan Anda.

Mitigasi

  • Hanya unggah aset sekali - Gunakan ID aset yang sama di seluruh objek dan pastikan aset yang sama, terutama mesh dan gambar, tidak diunggah secara terpisah beberapa kali.

  • Temukan dan perbaiki aset duplikat - Cari bagian mesh dan tekstur identik yang diunggah beberapa kali dengan ID yang berbeda.

    • Meskipun tidak ada API untuk mendeteksi kesamaan aset secara otomatis, Anda dapat mengumpulkan semua ID aset gambar di tempat Anda (baik secara manual atau dengan skrip), mengunduhnya, dan membandingkannya menggunakan alat perbandingan eksternal.
    • Untuk bagian mesh, strategi terbaik adalah mengambil ID mesh unik dan mengorganisasikannya berdasarkan ukuran untuk mengidentifikasi duplikat secara manual.
    • Alih-alih menggunakan tekstur terpisah untuk warna yang berbeda, unggah satu tekstur dan gunakan properti SurfaceAppearance.Color untuk menerapkan berbagai warna padanya.
  • Impor aset dalam peta secara terpisah - Alih-alih mengimpor seluruh peta sekaligus, impor dan bangun kembali aset dalam peta secara individu dan bangun kembali mereka. Pengimpor tidak melakukan de-duplication mesh, jadi jika Anda mengimpor peta besar dengan banyak ubin lantai terpisah, masing-masing ubin tersebut akan diimpor sebagai aset terpisah (meskipun mereka adalah duplikat). Ini dapat menyebabkan masalah kinerja dan memori di kemudian hari, karena setiap mesh diperlakukan sebagai individu dan memakan memori serta panggilan gambar.

  • Batasi piksel gambar tidak lebih dari jumlah yang diperlukan. Kecuali gambar menempati banyak ruang fisik di layar, biasanya hanya memerlukan paling banyak 512x512 piksel. Sebagian besar gambar kecil harus lebih kecil dari 256x256 piksel.

  • Gunakan lembar trim untuk memastikan penggunaan tekstur maksimum dalam peta 3D. Untuk langkah-langkah dan contoh tentang cara membuat lembar trim, lihat Buat lembar trim.

    Anda juga dapat mempertimbangkan untuk menggunakan lembar sprite untuk memuat banyak gambar UI kecil sebagai satu gambar. Anda kemudian dapat menggunakan ImageLabel.ImageRectOffset dan ImageLabel.ImageRectSize untuk menampilkan bagian dari lembar tersebut.

Waktu muat

Sebelum pemain dapat mulai bermain, klien harus menerima semuanya di ReplicatedFirst dan ReplicatedStorage, konten awal dari Workspace, dan aset apa pun yang dimuat sebelumnya oleh skrip Anda. Semakin banyak konten yang harus diunduh dan diproses klien selama waktu ini, semakin lama pemain menunggu. Untuk rincian setiap langkah dalam proses bergabung, lihat Identifikasi masalah kinerja.

Masalah umum

  • Streaming instance dinonaktifkan - Tanpa streaming instance, seluruh Workspace harus direplikasi ke klien sebelum pemain dapat masuk, jadi permainan dengan banyak bagian, model, dan aset memiliki waktu muat yang lebih lama secara proporsional.

  • Konten berlebihan di ReplicatedStorage - Segala sesuatu di ReplicatedStorage direplikasi ke setiap klien sebelum pemain dapat melihat atau berinteraksi dengan apa pun, terlepas dari apakah klien membutuhkannya segera. Model gratis dan aset yang diwarisi dapat secara diam-diam menambah beban yang signifikan.

  • Konten ReplicatedFirst yang berat - ReplicatedFirst direplikasi sebelum yang lainnya dan ada terutama untuk menampung layar pemuatan kustom. Setiap aset atau skrip tambahan di dalamnya menunda dimulainya fase replikasi utama.

  • Menggunakan PreloadAsync() secara berlebihan - Banyak permainan menerapkan layar pemuatan kustom dan menggunakan ContentProvider:PreloadAsync() untuk meminta aset sehingga gambar, suara, dan mesh diunduh di latar belakang. Pendekatan ini memastikan bagian penting dari permainan Anda sepenuhnya dimuat tanpa pop-in, tetapi kesalahan umum adalah memuat lebih banyak aset daripada yang sebenarnya diperlukan.

    Contoh praktik buruk adalah memuat seluruh Workspace. Meskipun ini mungkin mencegah pop-in tekstur, ini secara signifikan meningkatkan waktu muat.

    Praktik serupa lainnya adalah memanfaatkan ContentProvider.RequestQueueSize untuk memastikan bahwa semua aset yang diminta telah selesai dimuat. Namun, ini menghadirkan masalah yang sama dengan waktu muat yang meningkat secara signifikan, sementara juga menjadi metode yang tidak dapat diandalkan karena sifatnya yang berfluktuasi.

  • Skrip startup yang mahal - Eksekusi skrip berat dalam LocalScripts yang berjalan selama proses bergabung, seperti memuat struktur data besar secara sinkron, menunda transisi dari replikasi ke keadaan yang dapat dimainkan.

Mitigasi

  • Aktifkan streaming instance - Streaming hanya mengirim bagian dunia Anda yang dekat dengan titik spawn pemain pada bergabung awal, kemudian secara progresif mengalirkan sisanya saat pemain bergerak melalui permainan Anda. Untuk permainan yang belum menggunakannya, streaming adalah salah satu cara paling efektif untuk mengurangi waktu muat. Streaming diaktifkan secara default untuk tempat baru. Untuk langkah-langkah pengaturan, referensi properti, dan panduan migrasi, lihat Streaming instance.

  • Jaga ReplicatedStorage tetap ramping - Hanya simpan apa yang dibutuhkan klien pada saat mereka bergabung, seperti ModuleScripts bersama yang diperlukan oleh LocalScripts. Pindahkan model besar, audio, dan aset lain yang tidak diperlukan segera ke ServerStorage, dan pindahkan ke klien hanya ketika pemain membutuhkannya. Audit ReplicatedStorage secara teratur untuk konten yang tidak lagi Anda gunakan.

  • Jaga ReplicatedFirst tetap ramping - Batasi ReplicatedFirst pada apa yang diperlukan layar pemuatan Anda, seperti elemen UI dasar daripada tekstur besar atau model 3D, dan hindari perhitungan berat dalam skrip yang berjalan dari situ. Untuk panduan tentang membangun layar pemuatan kustom, termasuk kapan memanggil ReplicatedFirst:RemoveDefaultLoadingScreen(), lihat Layar pemuatan.

  • Hanya muat aset yang diperlukan - Gunakan ContentProvider:PreloadAsync() hanya dalam situasi yang diperlukan, yang mencakup:

    • Gambar di layar pemuatan.
    • Gambar penting dalam menu permainan Anda, seperti latar belakang tombol dan ikon.
    • Aset penting di area awal atau spawn.

    Jika Anda harus memuat sejumlah besar aset, kami merekomendasikan Anda menyediakan tombol Lewati Muat.

  • Tunda pekerjaan startup yang tidak penting - Muat konten yang belum dijangkau pemain, seperti panel UI yang belum mereka buka, hanya saat pertama kali dibutuhkan. Untuk pekerjaan inisialisasi yang harus terjadi lebih awal, sebar di beberapa bingkai daripada menjalankannya sekaligus. Untuk teknik, lihat Perhitungan skrip.

©2026 Roblox Corporation. Roblox, logo Roblox, dan Powering Imagination termasuk dalam merek dagang kami yang terdaftar dan tidak terdaftar di AS dan negara lainnya.