Roblox · Doors · урок 2
В каждом проёме — дверь с табличкой 01, 02, 03… Подходишь — дверь сама распахивается со скрипом.
Синим — что добавляем на этом уроке.
ServerStorage └─ Door (Model) — PrimaryPart = Primary ├─ Primary (Part) — копия Exit: прозрачная, CanCollide и CanQuery выкл. ├─ Spinner (Part) — петля сбоку, Anchored │ └─ WeldConstraint (WeldConstraint) — Part0 = Spinner, Part1 = Door ├─ Door (Part) — полотно; Anchored выкл. │ ├─ WeldConstraint (WeldConstraint) — Part0 = Door, Part1 = Label │ └─ Open (Sound) — скрип ├─ Label (Part) — табличка; Anchored выкл. │ └─ NumberGui (SurfaceGui) — Face — передняя грань │ └─ Number (TextLabel) └─ Trigger (Part) — перед дверью: прозрачный, CanCollide выкл., Anchored ServerScriptService └─ MainScript (Script) └─ Room (ModuleScript) └─ Door (ModuleScript)
Где: ServerScriptService → MainScript → Room · ModuleScript
Зачем: Ставит дверь с номером и открывает её при касании.
-- плавный поворот двери
local TS = game:GetService("TweenService")
-- здесь лежит образец двери
local SS = game:GetService("ServerStorage")
-- таблица модуля
local door = {}
-- открывает дверь
function door.Open(doorModel)
-- отмечаем: открыта
doorModel:SetAttribute("Open", true)
-- петля повёрнута на 90°
local cframe = doorModel.Spinner.CFrame * CFrame.Angles(0, math.rad(90), 0)
-- за полсекунды
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Linear)
-- поворачиваем петлю — дверь приварена и едет следом
TS:Create(doorModel.Spinner, tweenInfo, {CFrame = cframe}):Play()
-- скрип двери
doorModel.Door.Open:Play()
-- конец функции
end
-- ставит дверь на выход комнаты
function door.New(roomModel, number)
-- копия образца
local doorModel = SS.Door:Clone()
-- в дверной проём
doorModel:PivotTo(roomModel.Exit.CFrame)
-- закрыта
doorModel:SetAttribute("Open", false)
-- номер на табличке: 01, 02…
doorModel.Label.NumberGui.Number.Text = string.format("%02d", number)
-- кто-то подошёл к двери
doorModel.Trigger.Touched:Connect(function(otherPart)
-- модель, которой принадлежит деталь
local character = otherPart.Parent
-- это персонаж?
local humanoid = character:FindFirstChildOfClass("Humanoid")
-- не персонаж или уже открыта
if not humanoid or doorModel:GetAttribute("Open") then return end
-- открываем
door.Open(doorModel)
-- конец обработчика
end)
-- дверь — часть комнаты
doorModel.Parent = roomModel
-- отдаём дверь
return doorModel
-- конец функции
end
-- отдаём таблицу модуля
return doorГде: ServerScriptService → MainScript · ModuleScript
Зачем: Как раньше + дверь в каждой комнате.
-- здесь лежат образцы комнат
local SS = game:GetService("ServerStorage")
-- модуль дверей
local door = require(script.Door)
-- таблица модуля
local room = {}
-- редкость и правила комнат
room.info = require(script.RoomInfo)
-- генератор случайных чисел
room.random = Random.new()
-- куда был последний поворот
room.lastTurnDirection = nil
-- можно ли поставить эту комнату следующей
local function Allowed(name, info, prevRoom)
-- настройки предыдущей (у стартовой их нет)
local prevInfo = room.info[prevRoom.Name] or {}
-- образца нет — пропускаем
if not SS.RoomSamples:FindFirstChild(name) then return false end
-- две одинаковые подряд — скучно
if name == prevRoom.Name then return false end
-- два поворота в одну сторону — коридор замкнётся
if info.Direction and info.Direction == room.lastTurnDirection then return false end
-- две лестницы подряд — нельзя
if info.Stairs and prevInfo.Stairs then return false end
-- подходит
return true
-- конец функции
end
-- случайная комната с учётом редкости
function room.GetRandom(prevRoom)
-- сумма весов подходящих комнат
local totalRarity = 0
-- все комнаты из RoomInfo
for name, info in pairs(room.info) do
-- подходящие складываем
if Allowed(name, info, prevRoom) then totalRarity += info.Rarity end
-- конец перебора
end
-- понятная ошибка вместо зависания
if totalRarity == 0 then error("Нет подходящих комнат в ServerStorage.RoomSamples") end
-- случайное число от 1 до суммы
local randomRarity = room.random:NextInteger(1, totalRarity)
-- накопленный вес
local currentRarity = 0
-- снова по комнатам (порядок тот же)
for name, info in pairs(room.info) do
-- только подходящие
if Allowed(name, info, prevRoom) then
-- прибавляем вес
currentRarity += info.Rarity
-- число попало на эту комнату
if randomRarity <= currentRarity then
-- запоминаем поворот
if info.Direction then room.lastTurnDirection = info.Direction end
-- отдаём образец
return SS.RoomSamples[name]
-- конец проверки
end
-- конец проверки
end
-- конец перебора
end
-- конец функции
end
-- ставит новую комнату за предыдущей
function room.Generate(prevRoom, number)
-- копия случайной комнаты
local newRoom = room.GetRandom(prevRoom):Clone()
-- двигаем комнату за вход
newRoom.PrimaryPart = newRoom.Enter
-- вход новой — точно на выход предыдущей
newRoom:PivotTo(prevRoom.Exit.CFrame)
-- дверь на выходе с номером
door.New(newRoom, number)
-- показываем комнату
newRoom.Parent = workspace.GeneratedRooms
-- она станет «предыдущей» для следующей
return newRoom
-- конец функции
end
-- отдаём таблицу модуля
return roomГде: ServerScriptService · Script
Зачем: Дверь 01 в стартовой комнате и номера комнат.
-- модуль комнат
local room = require(script.Room)
-- модуль дверей
local door = require(script.Room.Door)
-- сколько комнат вместе со стартовой
local ROOMS = 10
-- первая «предыдущая» — стартовая
local prevRoom = workspace.StartRoom
-- дверь 01 в стартовой комнате
door.New(prevRoom, 1)
-- комнаты 2…10
for i = 2, ROOMS do
-- новая комната с дверью номер i
prevRoom = room.Generate(prevRoom, i)
-- конец цикла
endЗапусти Play (или Run) и убедись: