ROBLOX — Handles и ArcHandles

Автор: | 15 октября, 2024
Поделиться...

Понадобилось мне интерактивное управление объектами в игре «как в Roblox Studio» вечер покопавшись я нашёл два инструмента которые вроде как это позволяют.

  • Handles — управления в стиле смещение и изменение размера объекта
  • ArcHandles — управление поворотом объекта

Что даёт нам документация? Практически ничего. Но из неё можно узнать что:

  • это элементы GUI, а следовательно размещаться должны в StarterGUI, чтобы попадать в GUI игрока
  • т.к. это часть GUI, то взаимодействовать с ними мы можем только через локальные скрипты

Чем то это это напоминает UI Drag Detector и 3D Drag Detector т.к. по факту это их объединение в одно целое.

Ну да ладно. Вернёмся к нашим баранам.

Размещаем три парта в workspace и наши хандлеры в StarterGui:

В параметре Adornee каждого из них указываем на нужный парт и в итоге видим следующую картину (у простой ручки меняем параметр Style на Resize чтобы получить вариант Scale):

А далее не буду лить воду и просто дам локальные скрипты под каждой из ручек лежащий:

-- перемещение
local handle = script.Parent	-- управляющая ручка
local part = handle.Adornee		-- управляемый парт

local minSize = 1	-- минимальный размер
local oldDelta = 0	-- смещение от последнего движения

handle.MouseDrag:Connect(function(face, distance)	-- Enum направления и смещение
	local delta = distance - oldDelta				-- новое смещение
	
	local direction = Vector3.fromNormalId(face)	-- единичный вектор смещения
	
	-- смещение центра парта
	handle.Adornee:PivotTo(handle.Adornee.CFrame * CFrame.new(direction * delta))
	
	oldDelta = distance
end)

-- сброс смещения когда отпущена кнопка
handle.MouseButton1Up:Connect(function()
	oldDelta = 0
end)
-- изменение размера
local handle = script.Parent
local part = handle.Adornee

local minSize = 1	-- минимальный размер
local oldDelta = 0	-- смещение от последнего движения

handle.MouseDrag:Connect(function(face, distance) -- Enum направления и смещение
	local delta = distance - oldDelta	-- новое смещение
	
	local direction = Vector3.fromNormalId(face)	-- единичный вектор смещения
	
	local size = Vector3.new(math.abs(direction.X), math.abs(direction.Y), math.abs(direction.Z))	-- положительный вектор
	local endSize = handle.Adornee.Size + delta * size -- расчёт нового размера
	
	handle.Adornee.Size = endSize
	handle.Adornee:PivotTo(handle.Adornee.CFrame * CFrame.new(direction / 2 * delta))	-- смещение центра парта
	oldDelta = distance
end)

handle.MouseButton1Up:Connect(function()	-- сброс смещения когда отпущена кнопка
	oldDelta = 0
end)
-- изменение поворота
local handle = script.Parent	-- управляющая ручка
local part = handle.Adornee		-- управляемый парт

local lastCFrame = nil		-- стартовый CFrame
local increment = 2			-- скорость поворота

-- расчёт смещения с учётом ускорения
function round(number)
	return math.floor((number / increment) + 0.5) * increment
end
function AngleFromAxis(axis, r)
	local relativeAngle = math.rad(round(math.deg(r)))	-- получаем смещение угла

	return axis == Enum.Axis.X and {relativeAngle, 0, 0} -- поворот в зависимости от оси
		or axis == Enum.Axis.Y and {0, relativeAngle, 0} 
		or axis == Enum.Axis.Z and {0, 0, relativeAngle}
end

handle.MouseDrag:Connect(function(axis, relativeAngle, delta)
	-- сложение CFrame в плане поворота
	part.CFrame = lastCFrame * CFrame.Angles(unpack(AngleFromAxis(axis, relativeAngle))) 
end)

-- стартовый CFrame от которого начинается вращение
handle.MouseButton1Down:Connect(function()
	lastCFrame = part.CFrame
end)

Изменить их под себя вы можете самостоятельно. В том числе и в модуль запихнуть. 🙂


Поделиться...

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *