Detektory przeciągania 3D

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Instancja DragDetector ułatwia i zachęca do interakcji z obiektami 3D w doświadczeniu, takimi jak otwieranie drzwi i szuflad, przesuwanie części, chwytanie i rzucanie piłką do kręgli, naciąganie i strzelanie z procy, oraz wiele więcej. Kluczowe funkcje obejmują:

  • Umieść DragDetector pod dowolnym BasePart lub Model, aby uczynić go przeciągalnym za pomocą wszystkich wejść (mysz, dotyk, kontroler, VR), wszystko to bez jednej linii kodu.

  • Wybierz spośród kilku stylów przeciągania, zdefiniuj, jak obiekt reaguje na ruch, i opcjonalnie zastosuj limity osi lub ruchu.

  • Skrypty mogą reagować na manipulację przeciąganymi obiektami, aby napędzać UI lub podejmować decyzje logiczne, takie jak dostosowanie poziomu światła w pomieszczeniu na podstawie przesuwanego przełącznika.

  • Gracze mogą manipulować zablokowanymi częściami lub modelami, które pozostaną dokładnie tam, gdzie je umieścisz po zwolnieniu.

  • DragDetectors działają w Studio, o ile nie korzystasz z narzędzi Wybierz, Przenieś, Skaluj lub Obróć, co ułatwia testowanie i dostosowywanie przeciągalnych obiektów podczas edytowania.

Uczyń obiekty przeciągalnymi

Aby uczynić dowolną część lub model przeciągalnym, wystarczy dodać DragDetector jako bezpośredniego potomka.

  1. W oknie Eksploratora najedź kursorem na Part, MeshPart lub Model i kliknij przycisk ⊕. Wyświetli się menu kontekstowe.

  2. Z menu wstaw DragDetector.

  3. Domyślnie obiekt będzie teraz przeciągalny w płaszczyźnie ground, ale możesz dostosować jego DragStyle, zdefiniować jak reaguje na ruch i opcjonalnie zastosować limity osi lub ruchu.

Dostosowywanie detektorów przeciągania

Styl przeciągania

DragDetectors mapują ruch kursora na wirtualne linie i płaszczyzny w celu obliczenia proponowanego ruchu 3D. Dzięki właściwości DragStyle możesz wybierać spośród różnych mapowań, które odpowiadają Twoim potrzebom. Na przykład, TranslatePlane produkuje translację w wirtualnej płaszczyźnie, podczas gdy RotateAxis produkuje obrót wokół wirtualnej osi.

UstawienieOpis
TranslateLineRuch 1D wzdłuż Axis detektora, domyślnie wzdłuż osii Y świata.
TranslatePlaneRuch 2D w płaszczyźnie prostopadłej do Axis detektora, domyślnie w płaszczyźnie XZ świata.
TranslatePlaneOrLineRuch 2D w płaszczyźnie prostopadłej do Axis detektora oraz, gdy modyfikator jest aktywny, ruch 1D wzdłuż osii Axis detektora.
TranslateLineOrPlaneRuch 1D wzdłuż Axis detektora oraz, gdy modyfikator jest aktywny, ruch 2D w płaszczyźnie prostopadłej do Axis detektora.
TranslateViewPlaneRuch 2D w płaszczyźnie prostopadłej do widoku kamery. W tym trybie płaszczyzna jest nieustannie aktualizowana, nawet podczas przeciągania, i zawsze będzie zwrócona w kierunku aktualnego widoku kamery.
RotateAxisObrót wokół Axis detektora, domyślnie wzdłuż osii Y świata.
RotateTrackballObrót trackball, dodatkowo dostosowywany poprzez właściwości TrackballRadialPullFactor i TrackballRollFactor.
BestForDeviceTranslatePlaneOrLine dla myszy i kontrolera; TranslatePlane dla dotyku; 6DOF dla VR.
ScriptableOblicza pożądany ruch za pomocą funkcji niestandardowej dostarczonej poprzez SetDragStyleFunction().

Kierunek przeciągania

Domyślnie ruch 3D i związany z nim DragStyle mapują się na przestrzeń świata. Możesz jednak захотеть zmienić ReferenceInstance, Orientation lub Axis, na przykład podczas budowania detektorów przeciągania w modelach z regulowanymi częściami.

WłaściwośćOpisDomyślnie
ReferenceInstanceInstancja, której pivot zapewnia ramę odniesienia dla detektora przeciągania. DragFrame jest wyrażany względem tej ramy odniesienia, którą można uzyskać za pomocą GetReferenceFrame(). Jeśli rama odniesienia jest nil, translacja będzie w kierunku (lub w płaszczyźnie prostopadłej do) właściwości Axis w przestrzeni świata.nil
OrientationOkreśla YXZ obrót osi ruchu względem ramy odniesienia (nie zmienia orientacji samej ramy odniesienia). Linearna translacja i rotacja osiowe będą na tej obróconej osi Y, a translacja w płaszczyźnie XZ. Zmiana tej wartości automatycznie aktualizuje Axis i odwrotnie.(0, 0, 0)
AxisGłówna oś ruchu, wyrażona względem ramy odniesienia. Zmiana tej wartości automatycznie aktualizuje Orientation i odwrotnie.(0, 1, 0)

Reakcja na ruch

Właściwość ResponseStyle określa, jak obiekt reaguje na proponowany ruch, w zależności od tego, czy obiekt jest Anchored czy nie.

UstawienieZachowanie zablokowaneZachowanie niezablokowane
GeometricZarówno wewnątrz działającego doświadczenia, jak i w trybie edytora Studio, pozycja/orientacja zablokowanego obiektu będzie aktualizowana, aby dokładnie odzwierciedlać proponowany ruch.Dla niezablokowanego obiektu, zachowanie jest takie samo jak dla zablokowanego obiektu. Jednak w działającym doświadczeniu obiekt będzie zablokowany na początku przeciągania i przywrócony do niezablokowanego po zwolnieniu przeciągania.
PhysicalZablokowany obiekt domyślnie będzie miał zachowanie Geometric, ponieważ nie jest poddawany siłom.Niezablokowany obiekt będzie przenoszony przez siły ograniczające, które próbują przynieść go do pozycji/orientacji wskazanej przez proponowany ruch.
CustomObiekt nie poruszy się wcale, ale DragFrame nadal będzie aktualizowane i możesz reagować na manipulację przeciąganiem w dowolny sposób.(to samo co zablokowany)

Osi i limity ruchu

Domyślnie nie ma limitów 3D ruchu poza wrodzonymi ograniczeniami DragStyle. W razie potrzeby możesz zastosować minimalne i maksymalne limity dla translacji i rotacji. Zauważ jednak, że są to nie ograniczenia; jedynie utrudniają próby detektora przeciągania generowanie ruchu w celu pozostania w ramach limitów.

WłaściwościOpisDomyślnie

MinDragTranslation
MaxDragTranslation

Limity dla translacji przeciągania w każdym wymiarze. Jeśli MaxDragTranslation jest większa niż MinDragTranslation, translacja będzie ograniczona do tego zakresu.(0, 0, 0)

MinDragAngle
MaxDragAngle

Ważne tylko, jeśli DragStyle jest ustawione na RotateAxis. Jeśli MaxDragAngle jest większe niż MinDragAngle, rotacja będzie ograniczona do tego zakresu.0

Uprawnienia przeciągania

Uprawnienia graczy do interakcji z danym instancją detektora przeciągania można określić przez właściwość PermissionPolicy. Domyślnie jest ustawiona na Enum.DragDetectorPermissionPolicy.Everybody, a także może być zmieniana, aby wspierać kontrolowane uprawnienia skryptowe, jak pokazano w przykładzie kodu.

UstawienieOpis
NobodyŻaden gracz nie może interakcji z DragDetector.
EverybodyWszyscy gracze mogą interagować z DragDetector.
ScriptableUprawnienia do przeciągania graczy będą określane przez funkcję zarejestrowaną za pomocą SetPermissionPolicyFunction(). W tym ustawieniu brak rejestracji funkcji lub zwrócenie nieprawidłowego wyniku uniemożliwi wszystkim graczom przeciąganie.
DragDetector - Skryptowane uprawnienia przeciągania

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)

Odpowiedź fizyczna

Jeśli styl odpowiedzi detektora jest ustawiony na Physical i jest stosowany do niezablokowanego obiektu, obiekt ten будет przemieszczany przez siły ograniczające, które starają się przynieść go do pozycji/orientacji wskazanej przez proponowany ruch. Możesz dalej dostosować odpowiedź fizyczną za pomocą następujących właściwości:

WłaściwośćOpisDomyślnie
ApplyAtCenterOfMassKiedy fałsz, siła przeciągania jest stosowana w punkcie, w którym użytkownik klika. Gdy prawda, siła jest zastosowana w środku masy obiektu.false
MaxForceMaksymalna siła zastosowana, aby obiekt osiągnął swój cel.10000000
MaxTorqueMaksymalny moment obrotowy zastosowany, aby obiekt osiągnął swój cel.10000
ResponsivenessWyższe wartości sprawiają, że obiekt szybciej osiąga cel.10

Modyfikator wejściowy

Niektóre tryby DragStyle pozwalają użytkownikom przytrzymać klawisz/przycisk modyfikujący, aby manipulować przeciąganym obiektem w różny sposób. Domyślnie modyfikator to LeftControl na PC, ButtonR1 na kontrolerze, lub ButtonL2 na VR. Możesz dostosować te modyfikatory za pomocą właściwości KeyboardModeSwitchKeyCode, GamepadModeSwitchKeyCode, lub VRSwitchKeyCode instancji detektora przeciągania.

Replikacja

Gdy właściwość RunLocally jest fałszywa (domyślnie), klient interpretuje wszystkie wejścia, aby generować dane, które wysyła do serwera, aby zrealizować przeciąganie. W tym trybie wszystkie niestandardowe sygnały zdarzeń i zarejestrowane funkcje muszą znajdować się w serwerowych Scripts.

Gdy właściwość RunLocally jest prawdziwa, żadne z wydarzeń nie są replikowane do serwera. Wszystkie niestandardowe sygnały zdarzeń i zarejestrowane funkcje muszą znajdować się w lokalnych LocalScripts, a zmiany musisz propogować do serwera za pomocą zdarzeń zdalnych.

Odpowiedzi skryptów na klikanie i przeciąganie

Dzięki sygnałom zdarzeń, zmianom właściwości, Scriptable stylowi przeciągania oraz niestandardowym funkcjom, skrypty mogą reagować na manipulację przeciąganymi obiektami, aby napędzać UI lub podejmować decyzje logiczne, takie jak dostosowanie poziomu światła w pomieszczeniu na podstawie przesuwanego przełącznika.

Sygnały zdarzeń

Za pomocą następujących sygnałów zdarzeń możesz wykryć, kiedy użytkownik zaczyna, kontynuuje i kończy przeciąganie obiektu.

ZdarzenieOpis
DragStartUruchamia się, gdy użytkownik zaczyna przeciągać obiekt.
DragContinueUruchamia się, gdy użytkownik kontynuuje przeciąganie obiektu po tym, jak DragStart zostało zainicjowane.
DragEndUruchamia się, gdy użytkownik przestaje przeciągać obiekt.
DragDetector - Sygnały zdarzeń

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)

Zmiany ramki przeciągania

Oprócz sygnałów zdarzeń, możesz monitorować zmiany w DragFrame detektora bezpośrednio.

DragDetector - Zmiany w DragFrame

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

Skryptowany styl przeciągania

Jeśli ustawisz DragStyle detektora na Scriptable, możesz dostarczyć własną funkcję, która przyjmuje Ray i zwraca CFrame w przestrzeni świata. Detektor przeniesie ruch, aby przeciągany obiekt przeszedł do tej niestandardowej lokalizacji/orientacji.

DragDetector - Skryptowany DragStyle

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)
-- Wyklucz przeciągany obiekt z wykrywania 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)

Niestandardna funkcja ograniczeń

Detektory przeciągania nie mają wbudowanych reguł ruchu dotyczących siatek i snu, ale możesz zarejestrować niestandardowe funkcje ograniczeń, aby edytować DragFrame detektora, zanim zostanie zastosowany. Na przykład, możesz utrzymać ruch na siatce, zaokrąglając pozycje do wielokrotności kroku siatki, lub symulować grę w szachy z zasadami ruchu legalnymi dla każdej figury.

DragDetector - Niestandardowa funkcja ograniczenia

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)
-- Gdy to konieczne, usuń funkcję ograniczenia wywołując connection:Disconnect()

Przykład użycia

Niezablokowane obiekty fizyczne

Podstawowa implementacja detektorów przeciągania to gra o równowadze wieży, w której gracze muszą ostrożnie usunąć elementy i starać się utrzymać wieżę w pionie. W poniższej strukturze wieży każdy element ma dziecko DragDetector z domyślnym DragStyle ustawionym na TranslatePlane, aby gracze mogli ciągnąć elementy na zewnątrz, ale nie w górę ani w dół.

Zablokowane modele z regulowanymi częściami

Możesz łatwo tworzyć i udostępniać modele, które są głównie zablokowane, ale mają jedną lub więcej części/modeli, które gracze mogą przeciągać. Na przykład, poniższe biurko ma dwie szuflady, które gracze mogą otworzyć, aby sprawdzić, co jest w środku.

Detektory przeciągania i ograniczenia

Możesz łączyć detektory przeciągania z Constraints, na przykład marionetka. W poniższym ustawieniu uchwyty sterujące są zablokowane, a części ciała są niezablokowane, a ograniczenia trzymają marionetkę razem. Ruch uchwytów za pomocą TranslateViewPlane DragStyle sprawia, że marionetka tańczy, a poszczególne części ciała mogą być także przesuwane za pomocą detektorów przeciągania, podczas gdy model zachowuje swoją integralność.

3D interfejsy użytkownika

3D interfejsy użytkownika można łatwo osiągnąć za pomocą detektorów przeciągania, takich jak dostosowywanie jasności SpotLight na podstawie suwaka dimmera. Możesz także odkryć indywidualnie osie X i Z, aby kontrolować różne aspekty 3D interfejsu użytkownika, takie jak Size, Speed, i Color ParticleEmitter.

DragDetector - 3D Interfejs użytkownika

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
-- Dostosuj rozmiar i prędkość cząstek na podstawie czynnika X detektora przeciągania
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)
-- Dostosuj kolor cząstek na podstawie czynnika Z detektora przeciągania
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. Nazwa Roblox, logo Roblox oraz hasło „Powering Imagination” należą do naszych zarejestrowanych i niezarejestrowanych znaków towarowych na terenie Stanów Zjednoczonych oraz w innych krajach.