Detektor seret 3D

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

Instansi DragDetector memfasilitasi dan mendorong interaksi dengan objek 3D dalam pengalaman, seperti membuka pintu dan laci, menggeser bagian, mengambil dan melempar bola bowling, menarik kembali dan menembakkan ketapel, dan banyak lagi. Fitur utama termasuk:

  • Tempatkan DragDetector di bawah setiap BasePart atau Model untuk membuatnya dapat diseret melalui semua input (mouse, sentuhan, gamepad, dan VR), semuanya tanpa satu baris kode pun.

  • Pilih dari beberapa gaya seret, definisikan bagaimana objek merespons gerakan, dan secara opsional terapkan batas sumbu atau gerakan.

  • Skrip dapat merespons manipulasi objek yang diseret untuk mengendalikan UI atau membuat keputusan logis, seperti mengatur level cahaya di sebuah ruangan berdasarkan dimmer saklar dinding yang meluncur.

  • Pemain dapat memanipulasi bagian atau model yang terikat dan mereka akan tetap persis di tempat Anda meletakkannya setelah dilepas.

  • DragDetectors bekerja di Studio selama Anda tidak menggunakan alat Select, Move, Scale, atau Rotate, membuatnya lebih mudah untuk menguji dan menyesuaikan objek yang dapat diseret saat mengedit.

Membuat objek dapat diseret

Untuk membuat bagian atau model dapat diseret, cukup tambahkan DragDetector sebagai keturunan langsung.

  1. Di jendela Explorer, arahkan kursor ke Part, MeshPart, atau Model dan klik tombol ⊕. Menu konteks akan ditampilkan.

  2. Dari menu tersebut, masukkan DragDetector.

  3. Secara default, objek sekarang akan dapat diseret di bidang tanah, tetapi Anda dapat menyesuaikan DragStyle-nya, mendefinisikan bagaimana ia merespons gerakan, dan secara opsional menerapkan batas sumbu atau gerakan.

Sesuaikan detektor seret

Gaya seret

DragDetectors memetakan gerakan kursor ke garis dan bidang virtual untuk menghitung gerakan 3D yang diusulkan. Melalui properti DragStyle, Anda dapat memilih dari pemetaan yang berbeda sesuai dengan kebutuhan Anda. Misalnya, TranslatePlane menghasilkan translasi di bidang virtual, sedangkan RotateAxis menghasilkan rotasi tentang sumbu virtual.

PengaturanDeskripsi
TranslateLineGerakan 1D sepanjang Axis detektor, secara default sumbu Y dunia.
TranslatePlaneGerakan 2D di bidang yang tegak lurus dengan Axis detektor, secara default bidang XZ dunia.
TranslatePlaneOrLineGerakan 2D di bidang yang tegak lurus dengan Axis detektor dan, ketika modifikator aktif, gerakan 1D sepanjang Axis detektor.
TranslateLineOrPlaneGerakan 1D sepanjang Axis detektor dan, ketika modifikator aktif, gerakan 2D di bidang yang tegak lurus dengan Axis detektor.
TranslateViewPlaneGerakan 2D di bidang yang tegak lurus dengan pandangan kamera. Dalam mode ini, bidang selalu diperbarui, bahkan saat menyeret, dan akan selalu menghadap pandangan kamera saat ini.
RotateAxisRotasi tentang Axis detektor, secara default sumbu Y dunia.
RotateTrackballRotasi trackball, lebih lanjut disesuaikan melalui properti TrackballRadialPullFactor dan TrackballRollFactor.
BestForDeviceTranslatePlaneOrLine untuk mouse dan gamepad; TranslatePlane untuk sentuhan; 6DOF untuk VR.
ScriptableMenghitung gerakan yang diinginkan melalui fungsi khusus yang diberikan melalui SetDragStyleFunction().

Arah seret

Secara default, gerakan 3D dan DragStyle yang terkait dipetakan ke ruang dunia. Namun, Anda mungkin ingin mengubah ReferenceInstance, Orientation, atau Axis, misalnya saat membangun detektor seret ke dalam model dengan bagian yang dapat disesuaikan.

PropertiDeskripsiDefault
ReferenceInstanceSebuah instansi yang pivotnya menyediakan kerangka referensi untuk detektor seret. DragFrame dinyatakan relatif terhadap kerangka referensi ini yang dapat diambil melalui GetReferenceFrame(). Jika kerangka referensi adalah nil, translasi akan dilakukan dalam arah (atau dalam bidang yang tegak lurus dengan) properti Axis dalam ruang dunia.nil
OrientationMenentukan rotasi YXZ sumbu gerakan relatif terhadap kerangka referensi (tidak mengubah orientasi kerangka referensi itu sendiri). Translasi linier dan rotasi sumbu akan berada di sumbu Y yang diputar ulang ini, dan translasi planar di bidang XZ. Mengubah nilai ini secara otomatis memperbarui Axis dan sebaliknya.(0, 0, 0)
AxisSumbu utama gerakan, dinyatakan relatif terhadap kerangka referensi. Mengubah nilai ini secara otomatis memperbarui Orientation dan sebaliknya.(0, 1, 0)

Respons terhadap gerakan

Properti ResponseStyle menentukan bagaimana objek merespons gerakan yang diusulkan, tergantung pada apakah objek tersebut Anchored atau tidak.

PengaturanPerilaku TerkaitPerilaku Tidak Terkait
GeometricBaik di dalam pengalaman yang sedang berjalan maupun dalam mode edit Studio, posisi/orientasi objek yang terikat akan diperbarui untuk mencerminkan dengan tepat gerakan yang diusulkan.Untuk objek yang tidak terikat, perilakunya sama seperti objek yang terikat. Namun, dalam pengalaman yang sedang berjalan, objek ini akan terikat di awal seretan dan dipulihkan ke status tidak terikat saat seretan dilepaskan.
PhysicalObjek yang terikat akan default ke perilaku Geometric, karena tidak terpengaruh oleh gaya.Objek yang tidak terikat akan dipindahkan oleh gaya batas yang berusaha membawanya ke posisi/orientasi yang diinginkan yang diberikan oleh gerakan yang diusulkan.
CustomObjek tidak akan bergerak sama sekali, tetapi DragFrame tetap akan diperbarui dan Anda dapat merespons manipulasi seret sesuka Anda.(sama dengan terikat)

Batas sumbu & gerakan

Secara default, tidak ada batasan untuk gerakan 3D di luar batasan bawaan dari DragStyle. Jika perlu, Anda dapat menerapkan batas minimum dan maksimum untuk translasi dan rotasi. Perhatikan, bagaimanapun, bahwa ini bukan batasan; mereka hanya menghalangi upaya detektor seret untuk menghasilkan gerakan agar tetap dalam batas.

PropertiDeskripsiDefault

MinDragTranslation
MaxDragTranslation

Membatasi translasi seret di setiap dimensi. Jika MaxDragTranslation lebih besar dari MinDragTranslation, translasi akan dibatasi dalam rentang tersebut.(0, 0, 0)

MinDragAngle
MaxDragAngle

Hanya relevan jika DragStyle disetel ke RotateAxis. Jika MaxDragAngle lebih besar dari MinDragAngle, rotasi akan dibatasi dalam rentang tersebut.0

Izin seret

Izin pemain untuk berinteraksi dengan instansi detektor seret tertentu dapat ditentukan oleh properti PermissionPolicy. Ini disetel ke Enum.DragDetectorPermissionPolicy.Everybody secara default, dan juga dapat diubah untuk mendukung kontrol izin yang diprogram seperti yang ditunjukkan dalam contoh kode.

PengaturanDeskripsi
NobodyTidak ada pemain yang dapat berinteraksi dengan DragDetector.
EverybodySemua pemain dapat berinteraksi dengan DragDetector.
ScriptableIzin seret pemain akan ditentukan oleh fungsi yang terdaftar melalui SetPermissionPolicyFunction(). Di bawah pengaturan ini, kegagalan mendaftarkan fungsi atau mengembalikan hasil yang tidak valid akan mencegah semua pemain dari melakukan seret.
DragDetector - Izin Seret Terprogram

local dragDetector = script.Parent.DragDetector
dragDetector.PermissionPolicy = Enum.DragDetectorPermissionPolicy.Scriptable
dragDetector:SetPermissionPolicyFunction(function(player, part)
if player and player:GetAttribute("IsInTurn") then
return true
elseif part and not part:GetAttribute("IsDraggable") then
return false
else
return true
end
end)

Respons fisika

Dengan asumsi gaya respons dari detektor disetel ke Physical dan diterapkan pada objek yang tidak terikat, objek itu akan dipindahkan oleh gaya batas yang berusaha membawanya ke posisi/orientasi yang diberikan oleh gerakan yang diusulkan. Anda dapat lebih menyesuaikan respons fisik melalui properti berikut:

PropertiDeskripsiDefault
ApplyAtCenterOfMassKetika false, gaya seret diterapkan pada titik yang diklik pengguna. Ketika true, gaya diterapkan di pusat massa objek.false
MaxForceBesar maksimum gaya yang diterapkan agar objek mencapai tujuannya.10000000
MaxTorqueBesar maksimum torsi yang diterapkan agar objek mencapai tujuannya.10000
ResponsivenessNilai yang lebih tinggi menyebabkan objek mencapai tujuannya lebih cepat.10

Input modifikator

Beberapa mode DragStyle memungkinkan pengguna untuk menahan tombol/yang menjadi modifikator untuk memanipulasi objek yang diseret dengan cara yang berbeda. Secara default, modifikator adalah LeftControl di PC, ButtonR1 di gamepad, atau ButtonL2 di VR. Anda dapat menyesuaikan modifikator ini melalui KeyboardModeSwitchKeyCode, GamepadModeSwitchKeyCode, atau VRSwitchKeyCode dari instansi detektor seret.

Replikasi

Ketika properti RunLocally false (default), klien menginterpretasikan semua input untuk menghasilkan data yang dikirim ke server untuk melakukan seret. Dalam mode ini, semua sinyal acara kustom dan fungsi yang terdaftar harus ada di server Scripts.

Ketika properti RunLocally true, tidak ada acara yang direplikasi ke server. Semua sinyal acara kustom dan fungsi yang terdaftar harus ada di client LocalScripts dan Anda harus menggunakan acara jarak jauh untuk menyebarkan perubahan yang diperlukan ke server.

Respons skrip terhadap klik dan seret

Melalui sinyal acara, perubahan properti, gaya seret Scriptable, dan fungsi kustom, skrip dapat merespons manipulasi objek yang diseret untuk mengendalikan UI atau membuat keputusan logis, seperti mengatur level cahaya di sebuah ruangan berdasarkan dimmer saklar dinding yang meluncur.

Sinyal acara

Melalui sinyal acara berikut, Anda dapat mendeteksi kapan seorang pengguna memulai, melanjutkan, dan mengakhiri penyeretan sebuah objek.

AcaraDeskripsi
DragStartTerpicu ketika pengguna memulai penyeretan objek.
DragContinueTerpicu ketika pengguna melanjutkan penyeretan objek setelah DragStart diinisiasi.
DragEndTerpicu ketika pengguna berhenti menyeret objek.
DragDetector - Sinyal Acara

local dragDetector = script.Parent.DragDetector
local highlight = Instance.new("Highlight")
highlight.Enabled = false
highlight.Parent = script.Parent
dragDetector.DragStart:Connect(function()
highlight.Enabled = true
end)
dragDetector.DragContinue:Connect(function()
end)
dragDetector.DragEnd:Connect(function()
highlight.Enabled = false
end)

Perubahan frame seret

Selain sinyal acara, Anda dapat memantau perubahan pada DragFrame detektor secara langsung.

DragDetector - Perubahan DragFrame

local dragDetector = script.Parent.DragDetector
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
local currentDragTranslation = dragDetector.DragFrame.Position
print(currentDragTranslation)
end)

Gaya seret terprogram

Jika Anda mengatur DragStyle detektor ke Scriptable, Anda dapat menyediakan fungsi Anda sendiri yang menerima Ray dan mengembalikan CFrame ruang dunia. Detektor akan memindahkan gerakan agar objek yang diseret menuju lokasi/orientasi kustom tersebut.

DragDetector - Gaya Seret Terprogram

local Workspace = game:GetService("Workspace")
local dragDetector = script.Parent.DragDetector
dragDetector.DragStyle = Enum.DragDetectorDragStyle.Scriptable
local cachedHitPoint = Vector3.zero
local cachedHitNormal = Vector3.yAxis
local function followTheCursor(cursorRay)
-- Tidak termasuk objek yang diseret dari deteksi raycast
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {dragDetector.Parent}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local hitPoint = Vector3.zero
local hitNormal = Vector3.yAxis
local raycastResult = Workspace:Raycast(cursorRay.Origin, cursorRay.Direction, raycastParams)
if raycastResult then
hitPoint = raycastResult.Position
hitNormal = raycastResult.Normal.Unit
else
hitPoint = cachedHitPoint
hitNormal = cachedHitNormal
end
cachedHitPoint = hitPoint
cachedHitNormal = hitNormal
local lookDir1 = hitNormal:Cross(Vector3.xAxis)
local lookDir2 = hitNormal:Cross(Vector3.yAxis)
local lookDir = if lookDir1.Magnitude > lookDir2.Magnitude then lookDir1.Unit else lookDir2.Unit
return CFrame.lookAt(hitPoint, hitPoint + lookDir, hitNormal)
end
dragDetector:SetDragStyleFunction(followTheCursor)

Fungsi batasan kustom

Detektor seret tidak memiliki aturan gerakan bawaan tentang grid dan snapping, tetapi Anda dapat mendaftarkan fungsi batasan kustom untuk mengedit DragFrame detektor sebelum diterapkan. Misalnya, Anda dapat menjaga gerakan pada grid dengan membulatkan posisi ke kelipatan dari increment grid, atau mensimulasikan permainan catur dengan aturan gerakan yang sah untuk setiap pion.

DragDetector - Fungsi Batasan Kustom

local dragDetector = script.Parent.DragDetector
local startPartPosition = nil
local SNAP_INCREMENT = 4
dragDetector.DragStart:Connect(function()
startPartPosition = script.Parent.Position
end)
dragDetector.DragEnd:Connect(function()
startPartPosition = nil
end)
local function snapToWorldGrid(proposedMotion)
if startPartPosition == nil then
return proposedMotion
end
local snapIncrement = SNAP_INCREMENT // 1
if snapIncrement < 1 then
return proposedMotion
end
local newWorldPosition = startPartPosition + proposedMotion.Position
local roundedX = ((newWorldPosition.X / snapIncrement + 0.5) // 1) * snapIncrement
local roundedY = ((newWorldPosition.Y / snapIncrement + 0.5) // 1) * snapIncrement
local roundedZ = ((newWorldPosition.Z / snapIncrement + 0.5) // 1) * snapIncrement
local newRoundedWorldPosition = Vector3.new(roundedX, roundedY, roundedZ)
return proposedMotion.Rotation + (newRoundedWorldPosition - startPartPosition)
end
local connection = dragDetector:AddConstraintFunction(2, snapToWorldGrid)
-- Saat berlaku, hapus fungsi batasan dengan memanggil connection:Disconnect()

Contoh penggunaan

Objek fisik yang tidak terikat

Implementasi dasar dari detektor seret adalah permainan keseimbangan menara di mana pemain harus hati-hati menghapus bagian dan berusaha mempertahankan menara tetap tegak. Dalam struktur menara berikut, setiap bagian memiliki anak DragDetector dengan DragStyle default TranslatePlane sehingga pemain dapat menarik bagian ke luar tetapi tidak ke atas atau ke bawah.

Model terikat dengan bagian yang dapat disesuaikan

Anda dapat dengan mudah membuat dan berbagi model yang sebagian besar terikat, tetapi memiliki satu atau lebih bagian/model anak yang dapat diseret oleh pemain. Misalnya, meja berikut memiliki dua laci yang dapat dibuka pemain untuk memeriksa isi di dalamnya.

Detektor seret dan batasan

Anda dapat menggabungkan detektor seret dengan Constraints, misalnya boneka marionette. Dalam pengaturan berikut, pegangan kontrol terikat, bagian tubuh tidak terikat, dan batasan menjaga marionette tetap bersatu. Menggerakkan pegangan dengan gaya seret TranslateViewPlane DragStyle membuat marionette bergerak, dan bagian-bagian tubuh individu juga dapat dipindahkan dengan detektor seret, semua sementara model tetap utuh.

Antarmuka pengguna 3D

Antarmuka pengguna 3D dapat dengan mudah dicapai melalui detektor seret, seperti mengatur kecerahan dari SpotLight berdasarkan dimmer saklar geser. Anda juga dapat mendeteksi sumbu X dan Z secara individual untuk mengendalikan dua aspek berbeda dari antarmuka pengguna 3D, seperti Size, Speed, dan Color dari ParticleEmitter.

DragDetector - Antarmuka Pengguna 3D

local model = script.Parent
local slider = model.SliderPart
local originPart = model.OriginPart
local emitter = script.Parent.EmitterPart.ParticleEmitter
local dragDetector = slider.DragDetector
dragDetector.ReferenceInstance = originPart
dragDetector.MinDragTranslation = Vector3.zero
dragDetector.MaxDragTranslation = Vector3.new(10, 0, 10)
local dragRangeX = dragDetector.MaxDragTranslation.X - dragDetector.MinDragTranslation.X
local dragRangeZ = dragDetector.MaxDragTranslation.Z - dragDetector.MinDragTranslation.Z
local MIN_PARTICLE_SIZE = 1
local MAX_PARTICLE_SIZE = 1.5
local MIN_PARTICLE_SPEED = 2.5
local MAX_PARTICLE_SPEED = 5
local COLOR1 = Color3.fromRGB(255, 150, 0)
local COLOR2 = Color3.fromRGB(255, 0, 50)
local function updateParticles(emitter)
local dragFactorX = (dragDetector.DragFrame.Position.X - dragDetector.MinDragTranslation.X) / dragRangeX
local dragFactorZ = (dragDetector.DragFrame.Position.Z - dragDetector.MinDragTranslation.Z) / dragRangeZ
-- Sesuaikan ukuran dan kecepatan partikel berdasarkan faktor X detektor seret
emitter.Size = NumberSequence.new{
NumberSequenceKeypoint.new(0, 0),
NumberSequenceKeypoint.new(0.1, MIN_PARTICLE_SIZE + ((MAX_PARTICLE_SIZE - MIN_PARTICLE_SIZE) * dragFactorX)),
NumberSequenceKeypoint.new(1, 0)
}
local speed = MIN_PARTICLE_SPEED + ((MAX_PARTICLE_SPEED - MIN_PARTICLE_SPEED) * dragFactorX)
emitter.Speed = NumberRange.new(speed, speed * 1.2)
-- Sesuaikan warna partikel berdasarkan faktor Z dari detektor seret
local color = COLOR2:Lerp(COLOR1, dragFactorZ)
emitter.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, color),
ColorSequenceKeypoint.new(1, color)
}
end
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
updateParticles(emitter)
end)
©2026 Roblox Corporation. Roblox, logo Roblox, dan Powering Imagination termasuk dalam merek dagang kami yang terdaftar dan tidak terdaftar di AS dan negara lainnya.