Roblox
Belajar Luau 13: Dukungan HP dan Analytics
Membuat game Roblox nyaman dimainkan di HP dan mengukur perilaku pemain: menguji tampilan perangkat di Studio, UI untuk semua layar, input lintas perangkat, dan event Analytics.

Dua hal yang sering dilupakan pemula, padahal sangat menentukan apakah game bisa menghasilkan uang:
- Mayoritas pemain Roblox bermain di HP. Kalau tombolmu terlalu kecil atau tertutup jempol, pemain HP langsung keluar.
- Kamu tidak bisa memperbaiki yang tidak kamu ukur. Analytics menunjukkan di stage mana pemain menyerah dan barang apa yang dibeli.
| File | Jenis | Diletakkan di |
|---|---|---|
1-lari-semua-perangkat.client.luau |
LocalScript | StarterPlayer → StarterPlayerScripts |
2-info-perangkat.client.luau |
LocalScript | StarterPlayer → StarterPlayerScripts |
3-analytics.server.luau |
Script | ServerScriptService |
Konsep 1: Menguji tampilan HP di Studio
Di tab Test, cari tombol Device (ikon HP/tablet). Pilih misalnya iPhone 14 atau Galaxy S. Layar Studio akan berubah ukuran dan input mouse dianggap sebagai sentuhan.
Hal-hal yang perlu diperiksa:
- Semua tombol mudah ditekan dengan jempol, minimal sekitar 44×44 piksel
- Tidak ada UI yang tertutup joystick (kiri bawah) atau tombol lompat (kanan bawah)
- Teks masih terbaca di layar kecil
- Tidak ada UI yang terpotong di layar yang berponi (notch)
Konsep 2: Tips UI untuk semua ukuran layar
| Alat | Kegunaan |
|---|---|
UDim2.fromScale |
Ukuran mengikuti persentase layar (sudah dipakai sejak Pelajaran 9) |
UIAspectRatioConstraint |
Menjaga bentuk tetap, misalnya tombol bulat tetap bulat di layar lebar |
UITextSizeConstraint |
Membatasi ukuran huruf minimal dan maksimal saat memakai TextScaled |
UIScale |
Memperbesar atau memperkecil seluruh UI sekaligus |
ScreenGui.ScreenInsets |
Menghindari area poni dan tombol bawaan Roblox (biarkan bawaannya) |
Konsep 3: Input dari semua perangkat
Pemain PC memakai keyboard, pemain HP memakai layar sentuh, dan pemain konsol memakai gamepad. ContextActionService menangani ketiganya sekaligus dengan satu function:
ContextActionService:BindAction(
"Lari", -- nama aksi
saatLari, -- function yang dipanggil
true, -- true = buat tombol di layar HP otomatis
Enum.KeyCode.LeftShift, -- tombol keyboard
Enum.KeyCode.ButtonL3 -- tombol gamepad
)
Untuk mendeteksi jenis perangkat, pakai UserInputService:
UserInputService.TouchEnabledbernilai true kalau ada layar sentuhUserInputService.KeyboardEnabledbernilai true kalau ada keyboardUserInputService.GamepadEnabledbernilai true kalau ada gamepad
Konsep 4: Analytics
Buka create.roblox.com → Creations → game-mu → Analytics. Roblox sudah mencatat banyak data secara otomatis:
| Metrik | Artinya | Kenapa penting |
|---|---|---|
| D1 / D7 Retention | Persen pemain yang kembali 1 atau 7 hari kemudian | Algoritma Roblox lebih sering merekomendasikan game dengan retensi tinggi |
| Session Time | Lama rata-rata bermain per kunjungan | Makin lama, makin besar Premium Payouts |
| Payer Conversion | Persen pemain yang membeli sesuatu | Mengukur seberapa menarik barang yang kamu jual |
| ARPDAU | Rata-rata Robux per pemain aktif per hari | Mengukur kesehatan monetisasi |
Selain itu, kamu bisa mengirim event sendiri dari script lewat AnalyticsService:
| Jenis event | Contoh pertanyaan yang dijawab |
|---|---|
Funnel (LogOnboardingFunnelStepEvent) |
"Dari 100 pemain baru, berapa yang sampai checkpoint 1? Berapa yang sampai stage 5?" |
Progression (LogProgressionCompleteEvent) |
"Stage mana yang paling sering membuat pemain berhenti?" |
Economy (LogEconomyEvent) |
"Dari mana koin paling banyak didapat? Untuk apa paling banyak dipakai?" |
Custom (LogCustomEvent) |
Apa saja, misalnya "berapa kali pemain jatuh ke lava?" |
Data event muncul di dashboard Analytics setelah game dimainkan orang sungguhan. Biasanya ada jeda beberapa jam, dan event dari Studio tidak ikut dihitung.
Catatan: semua panggilan
AnalyticsServicedi script 3 dibungkuspcall. Kalau suatu saat Roblox mengubah aturannya, game-mu tidak rusak dan hanya muncul peringatan di Output. Kalau itu terjadi, cocokkan dengan dokumentasi resmi di create.roblox.com/docs (cari "AnalyticsService").
Langkah di Roblox Studio
- Pasang ketiga script sesuai tabel di atas.
- Tekan Play di mode PC biasa. Tahan Shift untuk berlari, dan label "💻 PC" muncul di pojok kanan atas.
- Hentikan, lalu pilih Test → Device → sebuah HP, kemudian Play lagi. Tombol Lari muncul di layar dan label berubah menjadi "📱 HP".
- Periksa seluruh UI dari Pelajaran 9–12 dengan checklist di Konsep 1. Perbaiki yang tertutup atau terlalu kecil.
Kode
1-lari-semua-perangkat.client.luau
- Jenis: LocalScript
- Letakkan di: StarterPlayer -> StarterPlayerScripts
local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local PENGALI_LARI = 1.6 -- 60% lebih cepat dari kecepatan sekarang
local player = Players.LocalPlayer
-- Kecepatan sebelum mulai lari. Disimpan supaya efek lain
-- (VIP, Sepatu Cepat) tidak hilang saat berhenti lari.
local kecepatanAsli = nil
local humanoidYangLari = nil
local function berhentiLari()
if humanoidYangLari and kecepatanAsli then
humanoidYangLari.WalkSpeed = kecepatanAsli
end
humanoidYangLari = nil
kecepatanAsli = nil
end
-- Function ini dipanggil saat tombol DITEKAN dan saat DILEPAS.
-- inputState memberi tahu yang mana.
local function saatAksiLari(namaAksi, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
local character = player.Character
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not humanoid or humanoidYangLari then
return Enum.ContextActionResult.Pass
end
humanoidYangLari = humanoid
kecepatanAsli = humanoid.WalkSpeed
humanoid.WalkSpeed = kecepatanAsli * PENGALI_LARI
elseif inputState == Enum.UserInputState.End
or inputState == Enum.UserInputState.Cancel then
berhentiLari()
end
-- Sink = input ini sudah ditangani, jangan diteruskan ke aksi lain
return Enum.ContextActionResult.Sink
end
ContextActionService:BindAction(
"Lari",
saatAksiLari,
true, -- buat tombol sentuh di HP
Enum.KeyCode.LeftShift,
Enum.KeyCode.ButtonL3
)
-- Atur tampilan tombol HP
ContextActionService:SetTitle("Lari", "Lari")
-- Posisi relatif terhadap area tombol lompat, di sebelah kirinya
ContextActionService:SetPosition("Lari", UDim2.new(0.2, 0, 0.1, 0))
-- Kalau mati saat sedang lari, lupakan humanoid lama
-- (character baru otomatis mulai dari kecepatan normal)
player.CharacterAdded:Connect(function()
humanoidYangLari = nil
kecepatanAsli = nil
end)
-- CATATAN KEAMANAN:
-- WalkSpeed karakter sendiri BISA diubah dari client (dan exploiter juga
-- bisa melakukannya). Untuk game kompetitif, server perlu memeriksa
-- kecepatan pemain. Lihat Pelajaran 16.
2-info-perangkat.client.luau
- Jenis: LocalScript
- Letakkan di: StarterPlayer -> StarterPlayerScripts
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local kamera = workspace.CurrentCamera
-- ------------------------------------------------------------
-- 1. Tebak jenis perangkat
-- ------------------------------------------------------------
local function jenisPerangkat()
if UserInputService.GamepadEnabled and not UserInputService.KeyboardEnabled then
return "Konsol", "🎮"
elseif UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled then
return "HP", "📱"
else
return "PC", "💻"
end
end
-- ------------------------------------------------------------
-- 2. Label kecil di kanan atas
-- ------------------------------------------------------------
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "InfoPerangkat"
screenGui.ResetOnSpawn = false
local label = Instance.new("TextLabel")
label.AnchorPoint = Vector2.new(1, 0)
label.Position = UDim2.fromScale(0.98, 0.02)
label.Size = UDim2.fromScale(0.15, 0.05)
label.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
label.BackgroundTransparency = 0.4
label.Font = Enum.Font.GothamMedium
label.TextScaled = true
label.TextColor3 = Color3.new(1, 1, 1)
label.Parent = screenGui
Instance.new("UICorner").Parent = label
-- UIAspectRatioConstraint: label selalu 4:1 (lebar : tinggi),
-- jadi tidak jadi gepeng di layar HP yang memanjang
local rasio = Instance.new("UIAspectRatioConstraint")
rasio.AspectRatio = 4
rasio.Parent = label
-- UITextSizeConstraint: huruf tidak terlalu kecil atau terlalu besar
local batasHuruf = Instance.new("UITextSizeConstraint")
batasHuruf.MinTextSize = 10
batasHuruf.MaxTextSize = 24
batasHuruf.Parent = label
screenGui.Parent = playerGui
-- ------------------------------------------------------------
-- 3. Perbarui saat ukuran layar berubah (HP diputar, jendela diubah)
-- ------------------------------------------------------------
local function perbarui()
local nama, ikon = jenisPerangkat()
local ukuran = kamera.ViewportSize
label.Text = `{ikon} {nama} {math.floor(ukuran.X)}×{math.floor(ukuran.Y)}`
end
perbarui()
kamera:GetPropertyChangedSignal("ViewportSize"):Connect(perbarui)
-- Pemain bisa mencolokkan gamepad atau keyboard di tengah permainan
UserInputService.LastInputTypeChanged:Connect(perbarui)
-- ------------------------------------------------------------
-- 4. Contoh pemakaian: perbesar UI di layar kecil
-- ------------------------------------------------------------
-- UIScale di ScreenGui memperbesar SEMUA isinya sekaligus.
-- Di sini, kalau layar sangat kecil (HP kecil), UI sedikit diperbesar
-- supaya teks tetap terbaca.
local skala = Instance.new("UIScale")
skala.Parent = screenGui
local function aturSkala()
local tinggi = kamera.ViewportSize.Y
if tinggi < 400 then
skala.Scale = 1.25
else
skala.Scale = 1
end
end
aturSkala()
kamera:GetPropertyChangedSignal("ViewportSize"):Connect(aturSkala)
3-analytics.server.luau
- Jenis: Script
- Letakkan di: ServerScriptService
- Butuh: leaderstats (Pelajaran 8/10), folder "Checkpoints"
local Players = game:GetService("Players")
local AnalyticsService = game:GetService("AnalyticsService")
local folderCheckpoint = workspace:WaitForChild("Checkpoints")
-- Bungkus semua panggilan Analytics dengan pcall.
-- Analytics tidak boleh membuat game rusak kalau terjadi masalah.
local function catat(namaEvent, fungsi)
local berhasil, pesanError = pcall(fungsi)
if not berhasil then
warn(`Analytics "{namaEvent}" gagal: {pesanError}`)
end
end
-- ------------------------------------------------------------
-- FUNNEL pemain baru: langkah-langkah awal yang ingin kita ukur.
-- Dashboard akan menunjukkan berapa persen pemain yang lolos tiap langkah.
-- Langkah harus dicatat berurutan: 1, 2, 3, ...
-- ------------------------------------------------------------
local LANGKAH_FUNNEL = {
{stage = 0, nama = "Masuk game"},
{stage = 1, nama = "Checkpoint pertama"},
{stage = 3, nama = "Stage 3"},
{stage = 5, nama = "Stage 5"},
}
local function catatFunnel(player, stage)
for nomorLangkah, langkah in ipairs(LANGKAH_FUNNEL) do
if langkah.stage == stage then
catat("funnel", function()
AnalyticsService:LogOnboardingFunnelStepEvent(player, nomorLangkah, langkah.nama)
end)
end
end
end
-- ------------------------------------------------------------
-- PEMANTAUAN per pemain
-- ------------------------------------------------------------
local function saatPemainMasuk(player)
local leaderstats = player:WaitForChild("leaderstats", 30)
if not leaderstats then
return
end
local stage = leaderstats:WaitForChild("Stage")
local koin = leaderstats:WaitForChild("Koin")
-- Funnel hanya untuk pemain yang benar-benar baru (stage masih 0)
local pemainBaru = stage.Value == 0
if pemainBaru then
catatFunnel(player, 0)
end
-- PROGRESSION + FUNNEL: setiap stage naik
local stageSebelumnya = stage.Value
stage.Changed:Connect(function(stageBaru)
if stageBaru > stageSebelumnya then
catat("progression", function()
AnalyticsService:LogProgressionCompleteEvent(
player,
"Obby", -- nama jalur progres
stageBaru, -- level yang diselesaikan
`Stage {stageBaru}`
)
end)
if pemainBaru then
catatFunnel(player, stageBaru)
end
end
stageSebelumnya = stageBaru
end)
-- ECONOMY: koin masuk (Source) dan keluar (Sink).
-- Catatan: cara ini hanya melihat SELISIH, jadi tidak tahu dari mana
-- koinnya berasal. Untuk data lebih detail, panggil LogEconomyEvent
-- langsung di tempat koin diberikan (script koin, toko, produk).
local koinSebelumnya = koin.Value
koin.Changed:Connect(function(koinBaru)
local selisih = koinBaru - koinSebelumnya
koinSebelumnya = koinBaru
if selisih == 0 then
return
end
catat("economy", function()
AnalyticsService:LogEconomyEvent(
player,
if selisih > 0
then Enum.AnalyticsEconomyFlowType.Source
else Enum.AnalyticsEconomyFlowType.Sink,
"Koin", -- nama mata uang
math.abs(selisih), -- jumlah (selalu positif)
koinBaru, -- saldo akhir
if selisih > 0
then Enum.AnalyticsEconomyTransactionType.Gameplay.Name
else Enum.AnalyticsEconomyTransactionType.Shop.Name
)
end)
end)
-- CUSTOM: jumlah kematian per stage (stage mana yang paling sulit?)
player.CharacterAdded:Connect(function(character)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
catat("custom", function()
AnalyticsService:LogCustomEvent(player, `MatiDiStage{stage.Value}`)
end)
end)
end)
end
Players.PlayerAdded:Connect(saatPemainMasuk)
for _, player in ipairs(Players:GetPlayers()) do
task.spawn(saatPemainMasuk, player)
end
-- Info untuk pengembang
print(`📊 Analytics aktif. {#folderCheckpoint:GetChildren()} checkpoint dipantau.`)
Error yang sering muncul
| Masalah | Penyebab |
|---|---|
| Tombol Lari tidak muncul di HP | Argumen ketiga BindAction bukan true, atau perangkat yang dipilih bukan layar sentuh |
| Shift memicu Shift Lock, bukan lari | Shift Lock dinyalakan pemain di pengaturan. Ganti tombol lari ke LeftControl jika perlu. |
| Kecepatan tidak kembali normal setelah lari | Character berganti (mati) saat sedang menahan tombol. Script ini sudah menangani kasus itu. |
| Event analytics tidak muncul di dashboard | Normal untuk event dari Studio, atau datanya belum diproses (tunggu beberapa jam) |
Latihan
- Stamina: lari hanya bisa selama 5 detik, lalu harus istirahat 3 detik. Tampilkan bar stamina di layar.
- Tombol khusus HP: tampilkan panel toko (Pelajaran 9) dalam keadaan tertutup di HP, dengan tombol kecil 🛒 untuk membukanya. Di PC, panel boleh tetap terbuka.
- Event lava: kirim
LogCustomEventsetiap kali pemain mati karena lava. Petunjuk: tambahkan di script kill brick (Pelajaran 7). - Analisis: kalau dashboard menunjukkan 80% pemain berhenti di stage 3, apa saja yang mungkin menjadi penyebabnya? Tulis 3 kemungkinan dan cara memperbaikinya.
Kunci jawaban
Coba kerjakan sendiri dulu sebelum membaca bagian ini.
Latihan 1: Stamina
Ganti seluruh isi 1-lari-semua-perangkat.client.luau dengan versi berstamina:
local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")
local PENGALI_LARI = 1.6
local STAMINA_MAKS = 5 -- detik lari
local WAKTU_PULIH = 3 -- detik dari habis sampai penuh lagi
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local stamina = STAMINA_MAKS
local menahanTombol = false
local sedangLari = false
local kecepatanAsli = nil
local humanoidYangLari = nil
-- ---------- UI bar stamina ----------
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "UIStamina"
screenGui.ResetOnSpawn = false
local latar = Instance.new("Frame")
latar.AnchorPoint = Vector2.new(0.5, 1)
latar.Position = UDim2.fromScale(0.5, 0.97)
latar.Size = UDim2.fromScale(0.25, 0.02)
latar.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
latar.Parent = screenGui
Instance.new("UICorner").Parent = latar
local isi = Instance.new("Frame")
isi.Size = UDim2.fromScale(1, 1)
isi.BackgroundColor3 = Color3.fromRGB(80, 200, 255)
isi.Parent = latar
Instance.new("UICorner").Parent = isi
screenGui.Parent = playerGui
-- ---------- Lari ----------
local function mulaiLari()
local character = player.Character
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not humanoid or sedangLari or stamina <= 0 then
return
end
sedangLari = true
humanoidYangLari = humanoid
kecepatanAsli = humanoid.WalkSpeed
humanoid.WalkSpeed = kecepatanAsli * PENGALI_LARI
end
local function berhentiLari()
if sedangLari and humanoidYangLari and kecepatanAsli then
humanoidYangLari.WalkSpeed = kecepatanAsli
end
sedangLari = false
humanoidYangLari = nil
kecepatanAsli = nil
end
local function saatAksiLari(_, inputState)
if inputState == Enum.UserInputState.Begin then
menahanTombol = true
mulaiLari()
elseif inputState == Enum.UserInputState.End
or inputState == Enum.UserInputState.Cancel then
menahanTombol = false
berhentiLari()
end
return Enum.ContextActionResult.Sink
end
ContextActionService:BindAction("Lari", saatAksiLari, true,
Enum.KeyCode.LeftShift, Enum.KeyCode.ButtonL3)
ContextActionService:SetTitle("Lari", "Lari")
player.CharacterAdded:Connect(function()
sedangLari = false
humanoidYangLari = nil
kecepatanAsli = nil
end)
-- ---------- Setiap frame: kurangi atau isi stamina ----------
-- Heartbeat terpicu setiap frame; dt = waktu sejak frame sebelumnya (detik)
RunService.Heartbeat:Connect(function(dt)
if sedangLari then
stamina = math.max(stamina - dt, 0)
if stamina == 0 then
berhentiLari() -- habis -> berhenti paksa
end
else
stamina = math.min(stamina + dt * (STAMINA_MAKS / WAKTU_PULIH), STAMINA_MAKS)
-- Masih menahan tombol dan stamina sudah pulih penuh -> lari lagi
if menahanTombol and stamina >= STAMINA_MAKS then
mulaiLari()
end
end
isi.Size = UDim2.fromScale(stamina / STAMINA_MAKS, 1)
isi.BackgroundColor3 = if stamina < 1
then Color3.fromRGB(255, 90, 90) -- merah saat hampir habis
else Color3.fromRGB(80, 200, 255)
end)
Rumus pemulihan: stamina 5 harus penuh dalam 3 detik, jadi bertambah 5 / 3 ≈ 1,67 per detik. Dikali dt supaya kecepatan pemulihan sama di HP lambat (30 FPS) dan PC cepat (144 FPS).
Keputusan desain: script ini membuat pemain hanya bisa lari lagi setelah stamina penuh (kalau tombol terus ditahan). Itulah maksud "istirahat 3 detik". Banyak game memilih membolehkan lari lagi kapan saja selama stamina > 0. Keduanya benar, tinggal pilih rasa yang diinginkan.
Latihan 2: Panel toko bisa dilipat di HP
Tambahkan di paling bawah 3-toko.client.luau:
local UserInputService = game:GetService("UserInputService")
local diHP = UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled
local tombolBuka = Instance.new("TextButton")
tombolBuka.Name = "BukaToko"
tombolBuka.AnchorPoint = Vector2.new(1, 0.5)
tombolBuka.Position = UDim2.fromScale(0.98, 0.5)
tombolBuka.Size = UDim2.fromScale(0.07, 0.07)
tombolBuka.BackgroundColor3 = Color3.fromRGB(60, 110, 200)
tombolBuka.TextScaled = true
tombolBuka.Text = "🛒"
tombolBuka.Parent = screenGui
Instance.new("UICorner").Parent = tombolBuka
-- Tombol tetap bulat di layar mana pun
local rasio = Instance.new("UIAspectRatioConstraint")
rasio.AspectRatio = 1
rasio.Parent = tombolBuka
local function aturTampilan(terbuka)
panel.Visible = terbuka
tombolBuka.Visible = not terbuka
end
tombolBuka.Activated:Connect(function()
aturTampilan(true)
end)
-- Tombol tutup di dalam panel
local tombolTutup = Instance.new("TextButton")
tombolTutup.LayoutOrder = 1000
tombolTutup.Size = UDim2.fromScale(0.9, 0.12)
tombolTutup.BackgroundColor3 = Color3.fromRGB(120, 50, 50)
tombolTutup.TextScaled = true
tombolTutup.TextColor3 = Color3.new(1, 1, 1)
tombolTutup.Text = "Tutup"
tombolTutup.Visible = diHP -- di PC tidak perlu tombol tutup
tombolTutup.Parent = panel
Instance.new("UICorner").Parent = tombolTutup
tombolTutup.Activated:Connect(function()
aturTampilan(false)
end)
-- Awal: HP = tertutup, PC = terbuka
aturTampilan(not diHP)
Latihan 3: Event analytics saat kena lava
Di 2-rintangan-tag.server.luau (Pelajaran 16) atau 2-kill-brick.server.luau (Pelajaran 7):
local Players = game:GetService("Players")
local AnalyticsService = game:GetService("AnalyticsService")
local function catatMatiLava(humanoid)
local player = Players:GetPlayerFromCharacter(humanoid.Parent)
if not player then
return -- NPC, bukan pemain
end
pcall(function()
AnalyticsService:LogCustomEvent(player, "MatiKenaLava")
end)
end
Lalu panggil catatMatiLava(humanoid) tepat setelah humanoid.Health = 0. Supaya tidak tercatat dua kali, panggil hanya kalau humanoid.Health > 0 sebelum diubah. Fungsi humanoidDari di Pelajaran 16 sudah memastikan hal ini.
Lebih bermanfaat lagi: sertakan di mana lavanya, supaya tahu lava mana yang paling banyak "memakan" pemain. Misalnya dengan nama event MatiKenaLava_{part.Name}, lalu beri setiap lava nama yang berbeda.
Latihan 4: Analisis, 80% pemain berhenti di stage 3
Tidak ada satu jawaban yang pasti. Ini beberapa kemungkinan beserta cara mengeceknya:
| Kemungkinan penyebab | Cara mengecek | Perbaikan |
|---|---|---|
| Terlalu sulit: lompatan terlalu jauh atau sempit | Event MatiDiStage3 jauh lebih tinggi dari stage lain |
Perpendek lompatan, tambah platform, pindahkan bagian sulit ke stage yang lebih jauh |
| Bingung arah: pemain tidak tahu harus ke mana | Kematian rendah tapi tetap berhenti; minta teman mencoba tanpa diberi tahu | Tambah tanda panah, warna jalur yang mencolok, atau papan petunjuk |
| Bug: checkpoint 3 tidak terdeteksi, atau pemain terjebak | Coba sendiri dengan teliti, cek Output, cek di HP | Perbaiki bug, lalu uji ulang |
| Membosankan: stage 1–3 terlalu mirip | Session time pendek walaupun kematian rendah | Tambah variasi: platform bergerak, pintu, atau hadiah koin |
| Masalah di HP saja | Bandingkan data pemain HP dan PC di dashboard | UI menutupi layar, lompatan sulit dengan joystick |
Langkah setelah memperbaiki: ubah satu hal saja, rilis update, lalu bandingkan angkanya beberapa hari kemudian. Kalau mengubah lima hal sekaligus, kamu tidak akan tahu mana yang sebenarnya membantu.
Discussion (0)
We store your optional name, your comment, and technical hashes (not your raw IP address) to prevent spam. A functional cookie lets you edit or delete your own comments from this browser. To request deletion, use the contact page.
No comments yet. Start the discussion.